2016-03-16 23 views
4

Рассмотрим следующие два класса:«Объект не является итерируемым» Ошибка ввода «x в y»?

class Foo0(object):             
    pass 

class Foo1(object): 
    def __contains__(self, _): 
     return False 

Ни один из них является итерацию, как можно наблюдать, пытаясь for i in Foo1(): pass:

Traceback (most recent call last): 
    File "stuff.py", line 11, in <module> 
    for i in Foo1(): pass 
TypeError: 'Foo1' object is not iterable 

Наоборот, 3 in Foo1() действует (как Foo1 имеет __contains__), в то время как 3 in Foo0() не является:

Traceback (most recent call last): 
    File "stuff.py", line 9, in <module> 
    3 in Foo0() 
TypeError: argument of type 'Foo0' is not iterable 

Я считаю ошибку ошибочной. Дело не в том, что Foo0 не является итерируемым - ведь Foo1 тоже не повторяется, так что это не неотъемлемая причина. Более того, поскольку @niemmi и @tobias_k правильно отмечают ниже, если класс не поддерживает __contains__, __iter__ используется как резерв, что является прямой причиной этой ошибки. Однако это ухудшает ситуацию, так как пользователь может попытаться решить эту ошибку, реализовав __iter__, что является очень неэффективным средством реализации __contains__.

Почему это было выбрано как ошибка?

ответ

7

Если объект не имеет метода __contains__, Python автоматически пытается перебрать его, чтобы узнать, может ли он найти этот элемент. Поскольку Foo0 не является итерируемым, вы увидите ошибку.

ОБНОВЛЕНИЕ: Python language reference объясняет это более детально:

Для классов, определенных пользователем, которые определяют содержит метод(), х ​​в у истинно тогда и только тогда, когда у. содержит (x).

Для определенного пользователя классов, которые не определяют содержит(), но сделать определение ITER(), х ​​в у верно, если некоторое значение г с й == г производятся во время итерации по у. Если во время итерации возникает исключение, это как бы в случае возникновения этого исключения.

Наконец, протокол итерация в старом стиле пробовал: если класс определяет GetItem(), х ​​в у истинно тогда и только тогда, когда существует неотрицательного целого индекса я такой, что х == у [ i], а все нижние целые индексы не вызывают исключение IndexError. (Если возникает какое-либо другое исключение, это как бы в случае возникновения этого исключения).

+2

Спасибо, @niemmi, это тоже мое понимание. Тем не менее, это объясняет *, как это происходит, а не если это намеченное обоснование дизайнеров языка. Хороший ответ. –

+1

Сообщение об ошибке должно, по-видимому, объяснить основную причину, а не как отказ резервного копирования также не удалось. – tripleee

Смежные вопросы