Подтвердить что ты не робот

Как проверить, является ли объект итератором в Python?

Я могу проверить метод next(), но этого достаточно? Существует ли идеотический путь?

4b9b3361

Ответ 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