有没有像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__可迭代的类。

其他回答

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类型的字符串说yes。

Python 3中的bytes对象是可迭代的True == is_iterable(b"string") == is_iterable("string".encode('utf-8')) Python 2和3中的bytearray对象是可迭代的True == is_iterable(bytearray(b"abc"))

O.P. hasattr(x, '__iter__')方法将对Python 3中的字符串说“是”,而在Python 2中对字符串说“否”(无论“或b”或u”)。感谢@LuisMasuelli注意到它也会让你在一个bug __iter__。

在Python <= 2.5中,你不能也不应该——iterable是一个“非正式的”接口。

但是从Python 2.6和3.0开始,你可以利用新的ABC(抽象基类)基础设施以及一些内置的ABC,这些ABC在collections模块中可用:

from collections import Iterable

class MyObject(object):
    pass

mo = MyObject()
print isinstance(mo, Iterable)
Iterable.register(MyObject)
print isinstance(mo, Iterable)

print isinstance("abc", Iterable)

现在,这是否可取,或者是否有效,只是一个惯例的问题。正如你所看到的,你可以将一个不可迭代的对象注册为Iterable——它将在运行时引发一个异常。因此,isinstance获得了一个“新的”含义——它只是检查“声明的”类型兼容性,这在Python中是一个很好的方法。

另一方面,如果你的对象不能满足你所需要的接口,你会怎么做?举个例子:

from collections import Iterable
from traceback import print_exc

def check_and_raise(x):
    if not isinstance(x, Iterable):
        raise TypeError, "%s is not iterable" % x
    else:
        for i in x:
            print i

def just_iter(x):
    for i in x:
        print i


class NotIterable(object):
    pass

if __name__ == "__main__":
    try:
        check_and_raise(5)
    except:
        print_exc()
        print

    try:
        just_iter(5)
    except:
        print_exc()
        print

    try:
        Iterable.register(NotIterable)
        ni = NotIterable()
        check_and_raise(ni)
    except:
        print_exc()
        print

如果对象不满足您的期望,则抛出TypeError,但如果已经注册了正确的ABC,则检查将毫无用处。相反,如果__iter__方法可用,Python将自动识别该类的object为Iterable。

如果你只是期望一个可迭代对象,遍历它,然后忘记它。另一方面,如果您需要根据输入类型执行不同的操作,那么您可能会发现ABC基础结构非常有用。

Duck typing

try:
    iterator = iter(the_element)
except TypeError:
    # not iterable
else:
    # iterable

# for obj in iterator:
#     pass

类型检查

使用抽象基类。它们至少需要Python 2.6,并且只适用于新样式的类。

from collections.abc import Iterable   # import directly from collections for Python < 3.3

if isinstance(the_element, Iterable):
    # iterable
else:
    # not iterable

然而,iter()更可靠一些,如文档所述:

检查isinstance(obj, Iterable)检测类 注册为Iterable或具有__iter__()方法,但是 它不会检测使用__getitem__()迭代的类 方法。唯一可靠的方法来确定一个对象是否 Is iterable调用iter(obj)。

在我的脚本中,我经常发现定义一个可迭代函数很方便。 (现在合并了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,可以简单地实现这段代码或上面的代码。

try:
  #treat object as iterable
except TypeError, e:
  #object is not actually iterable

不要检查你的鸭子是否真的是一只鸭子,看看它是否可迭代,就像它是可迭代的一样对待它,如果不是就抱怨。