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

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

38
задан Ethan Furman 26 March 2016 в 00:10
поделиться

2 ответа

В 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)

Edit: как указано в комментарии, вопрос фокусируется на том, является ли объект итератором***, а не итерабельным*** (все итераторы итерабельны, но не наоборот - не все итерабельные являются итераторами). isinstance(x, collections.Iterator) - это совершенно аналогичный способ проверки именно этого условия.

56
ответ дан 27 November 2019 в 03:27
поделиться

Объект является итеративным, если он реализует протокол итератора.
Вы можете проверить наличие метода __ iter __ () с помощью:

hasattr(object,'__iter__')

в Python 2.x этот подход пропускает объекты str и другие встроенные типы последовательностей, такие как unicode, xrange, buffer. Он работает в Python 3.

Другой способ - протестировать его с помощью метода iter:

try:
   iter(object)
except TypeError:
   #not iterable
16
ответ дан 27 November 2019 в 03:27
поделиться
Другие вопросы по тегам:

Похожие вопросы: