def is_iterable(x):
try:
0 in x
except TypeError:
return False
else:
return True
Это скажет да всем видам итерируемых объектов, но скажет нет строкам в Python 2 . (Это то, что я хочу, например, когда рекурсивная функция может принимать строку или контейнер строк. В этой ситуации просьба о прощении может привести к obfuscode, и лучше сначала спросить разрешение.)
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 () скажет yes строкам типа 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"))
Подход O.P. hasattr(x, '__iter__')
скажет да для строк в Python 3 и нет в Python 2 (независимо от того, ''
или b''
или u''
). Спасибо @LuisMasuelli за то, что заметил, что он также подведет вас к багги __iter__
.