有没有像isiterable这样的方法?到目前为止,我找到的唯一解决办法就是打电话
hasattr(myObj, '__iter__')
但我不确定这是否万无一失。
有没有像isiterable这样的方法?到目前为止,我找到的唯一解决办法就是打电话
hasattr(myObj, '__iter__')
但我不确定这是否万无一失。
当前回答
检查__iter__适用于序列类型,但在Python 2中检查字符串会失败。我也想知道正确的答案,在那之前,这里有一种可能性(这也适用于字符串): 试一试: Some_object_iterator = iter(some_object) except TypeError as te: 打印(some_object, 'is not iterable')
内置iter检查__iter__方法,如果是字符串,则检查__getitem__方法。
另一种通用的python方法是假设一个可迭代对象,如果它在给定对象上不起作用,则会优雅地失败。Python术语表:
python编程风格,通过检查对象的方法或属性签名来确定对象的类型,而不是通过与某些类型对象的显式关系(“如果它看起来像鸭子,并且嘎嘎叫得像鸭子,那么它一定是鸭子。”)通过强调接口而不是特定的类型,设计良好的代码通过允许多态替换来提高其灵活性。duck类型避免使用type()或isinstance()进行测试。相反,它通常采用EAFP(请求原谅比请求许可更容易)风格的编程。
...
试一试: _ = (e代表my_object中的e) 除了TypeError: 打印my_object, 'is not iterable'
collections模块提供了一些抽象基类,允许询问类或实例是否提供特定的功能,例如: 从集合。abc import Iterable if isinstance(e, Iterable): # e是可迭代的
但是,这不会检查通过__getitem__可迭代的类。
其他回答
根据Python 2术语表,可迭代对象是
所有序列类型(如list、str和tuple)和一些非序列类型(如dict和file)以及使用__iter__()或__getitem__()方法定义的任何类的对象。可迭代对象可用于for循环和许多其他需要序列的地方(zip(), map(),…)。当一个可迭代对象作为参数传递给内置函数iter()时,它将返回该对象的迭代器。
当然,考虑到Python的一般编码风格,基于“请求原谅比请求许可更容易”这一事实。,一般的期望是使用
try:
for i in object_in_question:
do_something
except TypeError:
do_something_for_non_iterable
但如果你需要显式检查它,你可以通过hasattr(object_in_question, "__iter__")或hasattr(object_in_question, "__getitem__")来测试可迭代对象。你需要检查两者,因为strs没有__iter__方法(至少在Python 2中没有,在Python 3中有),而且生成器对象没有__getitem__方法。
我一直不明白为什么python有callable(obj) -> bool,而没有iterable(obj) -> bool… 当然,hasattr(obj,'__call__')更容易,即使它更慢。
由于几乎所有其他答案都建议使用try/except TypeError,其中测试异常通常被认为是任何语言中不好的做法,这里是iterable(obj) -> bool的实现,我越来越喜欢并经常使用:
为了python 2,我将使用lambda来获得额外的性能提升… (在python 3中,你用什么来定义函数并不重要,def的速度与lambda大致相同)
iterable = lambda obj: hasattr(obj,'__iter__') or hasattr(obj,'__getitem__')
注意,这个函数对于带有__iter__的对象执行得更快,因为它不测试__getitem__。
大多数可迭代对象应该依赖于__iter__,而特殊情况下的对象则返回到__getitem__,尽管对于可迭代对象来说,这两者都是必需的。 (因为这是标准的,所以它也会影响C对象)
如果object是可迭代的,下面代码中的isiterable函数将返回True。如果不是iterable则返回False
def isiterable(object_):
return hasattr(type(object_), "__iter__")
例子
fruits = ("apple", "banana", "peach")
isiterable(fruits) # returns True
num = 345
isiterable(num) # returns False
isiterable(str) # returns False because str type is type class and it's not iterable.
hello = "hello dude !"
isiterable(hello) # returns True because as you know string objects are iterable
考虑到Python的duck类型,最简单的方法是捕捉错误(Python完全知道它期望从一个对象变成迭代器):
class A(object):
def __getitem__(self, item):
return something
class B(object):
def __iter__(self):
# Return a compliant iterator. Just an example
return iter([])
class C(object):
def __iter__(self):
# Return crap
return 1
class D(object): pass
def iterable(obj):
try:
iter(obj)
return True
except:
return False
assert iterable(A())
assert iterable(B())
assert iterable(C())
assert not iterable(D())
注:
如果异常类型相同,则区分对象是否不可迭代或已经实现了有bug的__iter__是无关紧要的:无论如何,您将无法迭代对象。 我想我理解你的担忧:如果我也可以依赖鸭类型来引发AttributeError,如果__call__没有为我的对象定义,那么callable如何作为检查存在,但这不是可迭代检查的情况? 我不知道答案,但你可以实现我(和其他用户)给出的函数,或者只是在你的代码中捕获异常(你在那部分的实现将像我写的函数一样——只要确保你将迭代器的创建与其余代码隔离开来,这样你就可以捕获异常并将其与另一个TypeError区分开来。
在我的脚本中,我经常发现定义一个可迭代函数很方便。 (现在合并了Alfe建议的简化):
import collections
def iterable(obj):
return isinstance(obj, collections.Iterable):
因此,您可以测试任何对象是否具有非常可读的可迭代形式
if iterable(obj):
# act on iterable
else:
# not iterable
就像你对可调用函数所做的那样
编辑:如果你安装了numpy,你可以简单地做: 简单地说是什么
def iterable(obj):
try: iter(obj)
except: return False
return True
如果没有numpy,可以简单地实现这段代码或上面的代码。