有没有像isiterable这样的方法?到目前为止,我找到的唯一解决办法就是打电话

hasattr(myObj, '__iter__')

但我不确定这是否万无一失。


当前回答

考虑到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区分开来。

其他回答

有很多方法来检查一个对象是否可迭代:

from collections.abc import Iterable
myobject = 'Roster'
  
if isinstance(myobject , Iterable):
    print(f"{myobject } is iterable") 
else:
   print(f"strong text{myobject } is not iterable")

如果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

这是不够的:__iter__返回的对象必须实现迭代协议(即next方法)。请参阅文档中的相关部分。

在Python中,一个好的实践是“尝试并查看”而不是“检查”。

我在这里找到了一个很好的解决方案:

isiterable = lambda obj: isinstance(obj, basestring) \
    or getattr(obj, '__iter__', False)

不是真的“正确”,但可以作为最常见的类型,如字符串,元组,浮动等快速检查…

>>> '__iter__' in dir('sds')
True
>>> '__iter__' in dir(56)
False
>>> '__iter__' in dir([5,6,9,8])
True
>>> '__iter__' in dir({'jh':'ff'})
True
>>> '__iter__' in dir({'jh'})
True
>>> '__iter__' in dir(56.9865)
False