def is_iterable(x): try: 0 in x except TypeError: return False else: return True
Это скажет «да» всем типам итерируемых объектов, но в Python 2 он будет указывать «нет» на строки (это то, что я хочу, например, когда рекурсивная функция может принимать строку или контейнер строк. эта ситуация, , прося прощение , может привести к обфуску, и лучше сначала спросить разрешение.)
import numpy class Yes: def __iter__(self): yield 1; yield 2; yield 3; class No: pass class Nope: def __iter__(self): return 'nonsense' assert is_iterable(Yes()) assert is_iterable(range(3)) assert is_iterable((1,2,3)) # tuple assert is_iterable([1,2,3]) # list assert is_iterable({1,2,3}) # set assert is_iterable({1:'one', 2:'two', 3:'three'}) # dictionary assert is_iterable(numpy.array([1,2,3])) assert is_iterable(bytearray("not really a string", 'utf-8')) assert not is_iterable(No()) assert not is_iterable(Nope()) assert not is_iterable("string") assert not is_iterable(42) assert not is_iterable(True) assert not is_iterable(None)
Многие другие стратегии здесь скажут «да» строкам. Используйте их, если это то, что вы хотите.
import collections import numpy assert isinstance("string", collections.Iterable) assert isinstance("string", collections.Sequence) assert numpy.iterable("string") assert iter("string") assert hasattr("string", '__getitem__')
Примечание: is_iterable () будет указывать да на строки типа
bytes
иbytearray
.
bytes
объекты в Python 3 являются итерабельными True == is_iterable(b"string") == is_iterable("string".encode('utf-8'))
В Python 2 такого типа нет. bytearray
объекты в Python 2 и 3 являются итерируемыми True == is_iterable(bytearray(b"abc"))
Подход OP hasattr(x, '__iter__')
скажет «да» к строкам в Python 3 и нет в Python 2 (независимо от того, ''
или b''
или u''
). Спасибо @LuisMasuelli за то, что вы заметили, что это также подведет вас на багги __iter__
.