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

hasattr(myObj, '__iter__')

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


当前回答

你可以试试这个:

def iterable(a):
    try:
        (x for x in a)
        return True
    except TypeError:
        return False

如果我们可以创建一个迭代它的生成器(但从不使用生成器,以免占用空间),那么它就是可迭代的。听起来像是"废话"一类的事。为什么首先需要确定一个变量是否可迭代?

其他回答

在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基础结构非常有用。

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

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

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

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

你可以试试这个:

def iterable(a):
    try:
        (x for x in a)
        return True
    except TypeError:
        return 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