Сначала я хочу уточнить, я НЕ спрашиваю, что такое «итератор».
Вот как термин «итерабельность» определяется в документе Python:
повторяемый
Объект, способный возвращать свои члены по одному. Примеры итераций включают все типы последовательностей (такие как list, str и tuple), а также некоторые непоследовательные типы, такие как dict, файловые объекты и объекты. любых классов, которые вы определяете с помощью метода __iter __ () или __getitem __ ().
Итерации можно использовать в цикле for и во многих других местах, где требуется последовательность (zip (), map (), ...). Когда итерируемый объект передается в качестве аргумента встроенной функции iter (), она возвращает итератор для объекта. Этот итератор подходит для одного прохода по набору значений. При использовании итераторов обычно нет необходимости вызывать iter () или самостоятельно работать с объектами итератора. Оператор for делает это автоматически, создавая временную безымянную переменную для хранения итератора на время цикла.
См. Также итератор, последовательность и генератор.
Как предложили другие люди, использование isinstance(e, collections.Iterable)
- это самый питонический способ проверить, является ли объект итерируемым.
Итак, я провел несколько тестов с Python 3.4.3:
from collections.abc import Iterable
class MyTrain:
def __getitem__(self, index):
if index > 3:
raise IndexError("that's enough!")
return index
for name in MyTrain():
print(name) # 0, 1, 2, 3
print(isinstance(MyTrain(), Iterable)) # False
Результат довольно странный: MyTrain
определил __getitem__
метод, но он не считается итерируемым объектом, не говоря уже о том, что он способен возвращать по одному числу за раз.
Затем я удалил __getitem__
и добавил метод __iter__
:
from collections.abc import Iterable
class MyTrain:
def __iter__(self):
print("__iter__ called")
pass
print(isinstance(MyTrain(), Iterable)) # True
for name in MyTrain():
print(name) # TypeError: iter() returned non-iterator of type 'NoneType'
Теперь он считается «истинным» итеративным объектом, несмотря на то, что он ничего не может произвести во время итерации.
Так я что-то неправильно понял или документация неверна?
isinstance
не будет проверять, что интерфейс реализован правильно, это не выяснится до тех пор, пока вы не попытаетесь его перебрать, а только то, что соответствующий метод (ы) (в данном случае только__iter__
). - person jonrsharpe   schedule 26.09.2015isinstance(e, collections.Iterable)
- это самый питонический способ проверить, является ли объект итерируемым - нет, я бы сказал, что попытка перебрать его - это самый питонический способ! - person jonrsharpe   schedule 26.09.2015iter(x)
и посмотреть, не повысится ли онTypeError
. - person ekhumoro   schedule 26.09.2015isinstance(e, collections.Iterable)
? - person laike9m   schedule 26.09.2015if is_iterable(thing): for whatever in thing:
, а затем реализовалиis_iterable
также сfor whatever in thing:
! - person jonrsharpe   schedule 26.09.2015iter
на самом деле то же самое, что просто попытаться перебрать его, но с дополнительным преимуществом, заключающимся в том, что итератор не используется первым. - person ekhumoro   schedule 26.09.2015iter
позволит вам проверить в этих обстоятельствах. - person jonrsharpe   schedule 26.09.2015