Я могу проверить метод next()
, но этого достаточно? Существует ли идеотический путь?
Как проверить, является ли объект итератором в Python?
Ответ 1
В Python 2.6 или выше запроектированная идиома для таких поведенческих проверок является "проверкой членства" с абстрактным базовым классом в модуле collections
стандартной библиотеки:
>>> import collections
>>> isinstance('ciao', collections.Iterable)
True
>>> isinstance(23, collections.Iterable)
False
>>> isinstance(xrange(23), collections.Iterable)
True
Действительно, такой тип проверок является основной причиной создания новых абстрактных базовых классов (второй важный - обеспечить "функциональность mixin" в некоторых случаях, поэтому они являются ABC, а не просто интерфейсами, - но это не относится к collections.Iterable
, оно существует строго для того, чтобы разрешить такие проверки с помощью isinstance
или issubclass
). ABC разрешают классы, которые на самом деле не наследуют от них, чтобы быть "зарегистрированными" в качестве подклассов, так что такие классы могут быть "подклассами" ABC для таких проверок; и в этом случае они могут выполнять все необходимые проверки специальных методов (__iter__
), поэтому вам не нужно.
Если вы застряли со старыми версиями Python, "лучше попросить прощения, чем разрешение":
def isiterable(x):
try: iter(x)
except TypeError: return False
else: return True
но это не так быстро и лаконично, как новый подход.
Обратите внимание, что для этого особого случая вам часто понадобятся строки специального кода (которые повторяются, но большинство контекстов приложения все равно хотят рассматривать как "скаляры" ). Какой бы подход вы ни использовали для проверки итеративности, если вам нужен такой специальный корпус, просто добавьте чек для isinstance(x, basestring)
- например:
def reallyiterable(x):
return not isinstance(x, basestring) and isinstance(x, collections.Iterable)
Изменить: как указано в комментарии, вопрос фокусируется на том, является ли объект итер *** атор ***, а не it iter *** способным *** (все итераторы повторяемы, но не наоборот - не все итерации являются итераторами). isinstance(x, collections.Iterator)
- совершенно аналогичный способ специально проверить это условие.
Ответ 2
Объект итерируется, если он реализует протокол итератора.
Вы можете проверить наличие метода __iter__()
с помощью:
hasattr(object,'__iter__')
в Python 2.x этот подход пропускает объекты str и другие встроенные типы последовательностей, такие как unicode, xrange, buffer. Он работает в Python 3.
Другой способ - проверить его с помощью метода iter:
try:
iter(object)
except TypeError:
#not iterable
Ответ 3
Чтобы быть итератором, объект должен пройти три теста:
-
obj
имеет метод__iter__
-
obj
имеет методnext
(или__next__
в Python 3) -
obj.__iter__()
возвращаетobj
Итак, тест с вашим собственным роликом будет выглядеть так:
def is_iterator(obj):
if (
hasattr(obj, '__iter__') and
hasattr(obj, 'next') and # or __next__ in Python 3
callable(obj.__iter__) and
obj.__iter__() is obj
):
return True
else:
return False