在Python中,如何确定对象是否可迭代?

wil*_*lem 994 python iterable

有方法isiterable吗?到目前为止我找到的唯一解决方案是打电话

hasattr(myObj, '__iter__')
Run Code Online (Sandbox Code Playgroud)

但我不确定这是多么万无一失.

mik*_*iku 795

  1. 检查__iter__序列类型的工作,但它会失败,例如Python 2中的字符串.我也想知道正确的答案,在此之前,这里有一种可能性(也适用于字符串):

    try:
        some_object_iterator = iter(some_object)
    except TypeError as te:
        print some_object, 'is not iterable'
    
    Run Code Online (Sandbox Code Playgroud)

    所述iter内置的检查的__iter__方法或串的情况下的__getitem__方法.

  2. 另一种通用的pythonic方法是假设一个可迭代的,然后如果它不能在给定的对象上工作则优雅地失败.Python词汇表:

    Python的编程风格,通过它的方法检查用于确定对象的类型或属性的签名,而不是由某些类型的对象("如果它看起来像一个明确的关系鸭子,叫声像鸭子,那一定是一个鸭子通过强调接口".)而不是特定类型,精心设计的代码通过允许多态替换来提高其灵活性.Duck-typing避免使用type()或isinstance()进行测试.相反,它通常采用EAFP(更容易请求宽恕而非许可)的编程风格.

    ...

    try:
       _ = (e for e in my_object)
    except TypeError:
       print my_object, 'is not iterable'
    
    Run Code Online (Sandbox Code Playgroud)
  3. collections模块提供了一些抽象基类,如果它们提供特定功能,它们可以询问类或实例,例如:

    from collections.abc import Iterable
    
    if isinstance(e, Iterable):
        # e is iterable
    
    Run Code Online (Sandbox Code Playgroud)

    但是,这不会检查可迭代的类__getitem__.

  • 如果`my_object`非常大(比如说,无限像`itertools.count()`)你的列表理解会占用大量的时间/内存.最好制作一个永远不会尝试构建(可能是无限的)列表的生成器. (81认同)
  • 请注意,在Python 3中:`hasattr(u"hello",'__ init __')`返回`True` (53认同)
  • 字符串*是*一个序列(`isinstance('',Sequence)== True`)*和*作为任何序列它*是*iterable(`isinstance('',Iterable)`).虽然`hasattr('','__ item__')== False`但它可能会令人困惑. (36认同)
  • `[e for my_object]`可能因其他原因引发异常,即`my_object`未定义或者`my_object`实现中可能存在错误. (31认同)
  • 如果*some_object*也会因其他原因(错误等)引发TypeError,该怎么办?我们如何从"不可迭代的TypeError"中告诉它? (14认同)
  • @max添加检查"TypeError"并没有解决Nick所描述的问题,因此Shaung的评论在某种意义上重申了Nick的评论.检查Arne建议的异常描述总是一个坏主意,因为这个描述是实现细节. (3认同)
  • @PiotrDobrogost是的,你是对的.可能会从更深的层引发"TypeError",并且下一版本中的异常消息可能会更改.我猜这就是为什么我对EAFP方法感到满意的时候,无论引起异常的原因是什么,我想要的行为都是一样的. (2认同)
  • 通过按照2对其进行迭代来检查对象是否可迭代的副作用是您将使用生成器/迭代器的第一项,这可能会产生一些不良后果. (2认同)
  • (2)只是(1)的一个可怕且不直观的版本.在我尝试之前,我实际上没想到能正常工作.如果对象不可迭代,创建生成器将立即抛出异常并不明显.我认为如果将其删除,答案会更好. (2认同)
  • `xrange` 是一个没有 `__iter__` 方法的对象,也不是一个序列,但它是可迭代的。 (2认同)
  • 还有一个案例。获取一个您想要为其提供 __getitem__` 的对象,但您不想允许迭代。要强制执行此操作,您可以实现“__iter__”,但会出现错误。在这种情况下,“isinstance(x, Iterable)”实际上会导致误报。这可能看起来很学术,但在 PySpark 中,有一个“Column”对象正是以这种方式实现的。 (2认同)

Geo*_*lly 549

鸭打字

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

# for obj in iterator:
#     pass
Run Code Online (Sandbox Code Playgroud)

类型检查

使用抽象基类.他们至少需要Python 2.6并且只适用于新式类.

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

if isinstance(theElement, Iterable):
    # iterable
else:
    # not iterable
Run Code Online (Sandbox Code Playgroud)

但是,iter()文档所述,它更可靠:

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

  • 来自Luciano Ramalho的"Fluent Python":从Python 3.4开始,检查对象x是否可迭代的最准确方法是调用iter(x)并处理TypeError异常(如果不是).这比使用isinstance(x,abc.Iterable)更准确,因为iter(x)也考虑了遗留__getitem__方法,而Iterable ABC则没有. (14认同)
  • 在对象上调用iter()可能是一项昂贵的操作(请参阅Pytorch中的DataLoader,它会在iter()上派生/产生多个进程)。 (2认同)
  • 似乎 *enumerate()* 与 iter() (Python 3) 具有相同的效果,如果您要做的下一件事是枚举序列,这可能会简化一些事情 - 不需要事先显式 iter() ,因为如有必要,enumerate() 将自行引发适当的异常。 (2认同)

tim*_*geb 103

我想更多地了解窗帘背后的相互作用iter,__iter__以及__getitem__幕后发生的事情.有了这些知识,你就能理解为什么你能做的最好

try:
    iter(maybe_iterable)
    print('iteration will probably work')
except TypeError:
    print('not iterable')
Run Code Online (Sandbox Code Playgroud)

我将首先列出事实,然后快速提醒您for在python中使用循环时会发生什么,然后进行讨论以说明事实.

事实

  1. 如果至少满足下列条件之一,则可以o通过调用从任何对象获取迭代器iter(o):

    a)o有一个__iter__返回迭代器对象的方法.迭代器是具有__iter____next__(Python 2 :)方法的任何对象next.

    b)o有一种__getitem__方法.

  2. 检查Iterableor 的实例Sequence或检查属性__iter__是不够的.

  3. 如果一个对象o只实现__getitem__,但不会__iter__,iter(o)它将构造一个迭代器,它尝试从o整数索引中获取项目,从索引0开始.迭代器将捕获IndexError所引发的任何(但没有其他错误),然后StopIteration自行引发.

  4. 从最普遍的意义上讲,iter除了尝试之外,没有办法检查返回的迭代器是否合理.

  5. 如果一个对象o实现__iter__,该iter函数将确保返回的对象__iter__是一个迭代器.如果对象仅实现,则不进行健全性检查__getitem__.

  6. __iter__胜.如果一个对象o同时实现了__iter____getitem__,iter(o)将调用__iter__.

  7. 如果要使自己的对象可迭代,请始终实现该Iterable方法.

__iter__ 循环

为了跟进,您需要了解Sequence在Python中使用循环时会发生什么.如果您已经知道,请随意跳到下一部分.

当您使用for某个可迭代对象时for,Python会调用for item in o并期望迭代器对象作为返回值.迭代器是实现o(或iter(o)在Python 2中)方法和__next__方法的任何对象.

按照惯例,next迭代器的方法应该返回对象本身(即__iter__).Python然后调用__iter__迭代器直到return self被引发.所有这些都是隐式发生的,但以下演示使其可见:

import random

class DemoIterable(object):
    def __iter__(self):
        print('__iter__ called')
        return DemoIterator()

class DemoIterator(object):
    def __iter__(self):
        return self

    def __next__(self):
        print('__next__ called')
        r = random.randint(1, 10)
        if r == 5:
            print('raising StopIteration')
            raise StopIteration
        return r
Run Code Online (Sandbox Code Playgroud)

迭代next:

>>> di = DemoIterable()
>>> for x in di:
...     print(x)
...
__iter__ called
__next__ called
9
__next__ called
8
__next__ called
10
__next__ called
3
__next__ called
10
__next__ called
raising StopIteration
Run Code Online (Sandbox Code Playgroud)

讨论和插图

在第1点和第2点:获取迭代器和不可靠的检查

考虑以下课程:

class BasicIterable(object):
    def __getitem__(self, item):
        if item == 3:
            raise IndexError
        return item
Run Code Online (Sandbox Code Playgroud)

StopIteration使用实例调用DemoIterable将返回迭代器而没有任何问题因为iter实现BasicIterable.

>>> b = BasicIterable()
>>> iter(b)
<iterator object at 0x7f1ab216e320>
Run Code Online (Sandbox Code Playgroud)

但是,重要的是要注意,BasicIterable没有__getitem__属性,并且不被视为b或的实例__iter__:

>>> from collections import Iterable, Sequence
>>> hasattr(b, '__iter__')
False
>>> isinstance(b, Iterable)
False
>>> isinstance(b, Sequence)
False
Run Code Online (Sandbox Code Playgroud)

这就是Luciano Ramalho的Fluent Python建议调用Iterable和处理潜力Sequence作为检查对象是否可迭代的最准确方法的原因.直接从书中引用:

从Python 3.4开始,检查对象iter是否可迭代的最准确方法是调用TypeError并处理x异常(如果不是).这比使用更准确iter(x),因为TypeError还考虑了遗留isinstance(x, abc.Iterable)方法,而iter(x)ABC则没有.

在第3点:迭代仅提供__getitem__但不提供的对象Iterable

__getitem__按预期迭代一个工作实例:Python构造一个迭代器,它尝试按索引获取项目,从零开始,直到__iter__引发一个.演示对象的BasicIterable方法只返回由返回的迭代器IndexError作为参数提供__getitem__的内容item.

>>> b = BasicIterable()
>>> it = iter(b)
>>> next(it)
0
>>> next(it)
1
>>> next(it)
2
>>> next(it)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration
Run Code Online (Sandbox Code Playgroud)

需要注意的是,迭代器抛出__getitem__(self, item)时,它不能返回的下一个项目,而且iter它提高了StopIteration内部处理.这就是为什么循环IndexError使用item == 3循环按预期工作的原因:

>>> for x in b:
...     print(x)
...
0
1
2
Run Code Online (Sandbox Code Playgroud)

这是另一个例子,以便BasicIterable通过索引尝试访问项目来驱动返回迭代器的概念.for不继承iter,这意味着实例将没有WrappedDict方法.

class WrappedDict(object): # note: no inheritance from dict!
    def __init__(self, dic):
        self._dict = dic

    def __getitem__(self, item):
        try:
            return self._dict[item] # delegate to dict.__getitem__
        except KeyError:
            raise IndexError
Run Code Online (Sandbox Code Playgroud)

请注意,调用dict委托给__iter__方括号表示法只是一种简写.

>>> w = WrappedDict({-1: 'not printed',
...                   0: 'hi', 1: 'StackOverflow', 2: '!',
...                   4: 'not printed', 
...                   'x': 'not printed'})
>>> for x in w:
...     print(x)
... 
hi
StackOverflow
!
Run Code Online (Sandbox Code Playgroud)

在第4点和第5点:__getitem__调用时检查迭代器dict.__getitem__:

iter被调用的对象__iter__,iter(o)将确保的返回值o,如果方法存在,是一个迭代器.这意味着返回的对象必须实现iter(或__iter__在Python 2中)和__next__.next不能对仅提供的对象执行任何健全性检查__iter__,因为它无法检查对象的项是否可通过整数索引访问.

class FailIterIterable(object):
    def __iter__(self):
        return object() # not an iterator

class FailGetitemIterable(object):
    def __getitem__(self, item):
        raise Exception
Run Code Online (Sandbox Code Playgroud)

请注意,从iter实例构造迭代器会立即失败,同时从__getitem__成功构造迭代器,但会在第一次调用时抛出异常FailIterIterable.

>>> fii = FailIterIterable()
>>> iter(fii)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: iter() returned non-iterator of type 'object'
>>>
>>> fgi = FailGetitemIterable()
>>> it = iter(fgi)
>>> next(it)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/path/iterdemo.py", line 42, in __getitem__
    raise Exception
Exception
Run Code Online (Sandbox Code Playgroud)

第6点:FailGetItemIterable胜利

这个很简单.如果一个对象实现__next____iter__,__iter__将调用__getitem__.考虑以下课程

class IterWinsDemo(object):
    def __iter__(self):
        return iter(['__iter__', 'wins'])

    def __getitem__(self, item):
        return ['__getitem__', 'wins'][item]
Run Code Online (Sandbox Code Playgroud)

循环实例时的输出:

>>> iwd = IterWinsDemo()
>>> for x in iwd:
...     print(x)
...
__iter__
wins
Run Code Online (Sandbox Code Playgroud)

在第7点:您的可迭代类应该实现 iter

您可能会问自己,为什么大多数内置序列都会__iter__实现一个__iter__方法list就足够了.

class WrappedList(object): # note: no inheritance from list!
    def __init__(self, lst):
        self._list = lst

    def __getitem__(self, item):
        return self._list[item]
Run Code Online (Sandbox Code Playgroud)

毕竟,在重复上面的类,它代表调用的情况下__iter__,以__getitem__(使用方括号),将正常工作:

>>> wl = WrappedList(['A', 'B', 'C'])
>>> for x in wl:
...     print(x)
... 
A
B
C
Run Code Online (Sandbox Code Playgroud)

您的自定义iterables应实现的原因__getitem__如下:

  1. 如果实现list.__getitem__,实例将被视为iterables,__iter__并将返回__iter__.
  2. 如果返回的对象isinstance(o, collections.abc.Iterable)不是迭代器,True则会立即失败并引发一个__iter__.
  3. iter出于向后兼容性原因,存在特殊处理.再次从Fluent Python引用:

这就是为什么任何Python序列都是可迭代的:它们都是实现的TypeError.事实上,标准序列也实现了__getitem__,你的也应该实现,因为由于__getitem__向后兼容性的原因而存在特殊处理,并且可能在将来消失(尽管我写这篇文章时并没有弃用).


Pek*_*rck 88

我最近一直在研究这个问题。基于此,我的结论是,现在这是最好的方法:

from collections.abc import Iterable   # drop `.abc` with Python 2.7 or lower

def iterable(obj):
    return isinstance(obj, Iterable)
Run Code Online (Sandbox Code Playgroud)

上面已经推荐过,但普遍的共识是使用iter()会更好:

def iterable(obj):
    try:
        iter(obj)
    except Exception:
        return False
    else:
        return True
Run Code Online (Sandbox Code Playgroud)

我们iter()在我们的代码中也为此目的使用过,但我最近开始对那些只__getitem__被认为是可迭代的对象感到越来越恼火。__getitem__在不可迭代对象中有正当理由,并且上面的代码不能很好地工作。作为一个现实生活中的例子,我们可以使用Faker。上面的代码报告它是可迭代的,但实际上尝试迭代它会导致AttributeError(用 Faker 4.0.2 测试):

>>> from faker import Faker
>>> fake = Faker()
>>> iter(fake)    # No exception, must be iterable
<iterator object at 0x7f1c71db58d0>
>>> list(fake)    # Ooops
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/.../site-packages/faker/proxy.py", line 59, in __getitem__
    return self._factory_map[locale.replace('-', '_')]
AttributeError: 'int' object has no attribute 'replace'
Run Code Online (Sandbox Code Playgroud)

如果我们使用insinstance(),我们不会意外地认为 Faker 实例(或任何其他只有 的对象__getitem__)是可迭代的:

>>> from collections.abc import Iterable
>>> from faker import Faker
>>> isinstance(Faker(), Iterable)
False
Run Code Online (Sandbox Code Playgroud)

较早的答案评论说,使用iter()更安全,因为在 Python 中实现迭代的旧方法是基于__getitem__这种isinstance()方法的,而该方法不会检测到这一点。这对于旧的 Python 版本可能是正确的,但基于我非常详尽的测试,isinstance()现在效果很好。唯一isinstance()不起作用但起作用的情况iter()UserDict在使用 Python 2 时。如果这是相关的,则可以使用它isinstance(item, (Iterable, UserDict))来覆盖。

  • 我得出了同样的结论,但出于不同的原因。使用“iter”会导致我们的一些使用“预缓存”的代码不必要地减慢速度。如果 `__iter__` 代码很慢,那么调用 `iter` 也会很慢......任何时候你只想看看某些东西是否可迭代。 (3认同)
  • 是否值得在最后一点添加注释,指出开发人员不再积极支持 Python 2,并且如果可以选择 Python 3,则不应将其用于新代码? (3认同)

jld*_*ont 31

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

在Python中,一个好的做法是"尝试看"而不是"检查".

  • @willem"许可"和"宽恕"两种风格都有资格作为鸭子打字.如果你问一个对象可以*做什么*而不是它*是什么*,那就是鸭子打字.如果你使用内省,那就是"许可"; 如果你只是试着这样做,看它是否有效,那就是"宽恕". (14认同)
  • "鸭子打字"我相信?:) (9认同)
  • @willem:或"不要求许可,但请原谅";-) (9认同)

Ala*_*oni 22

在Python <= 2.5中,你不能也不应该 - iterable是一个"非正式"的接口.

但是,从Python 2.6和3.0开始,您可以利用新的ABC(抽象基类)基础结构以及集合模块中提供的一些内置ABC:

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)
Run Code Online (Sandbox Code Playgroud)

现在,无论这是可取的还是实际的,只是一个惯例问题.如您所见,您可以将非可迭代对象注册为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
Run Code Online (Sandbox Code Playgroud)

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

所以,如果你只是期望一个迭代,迭代它并忘记它.另一方面,如果您需要根据输入类型执行不同的操作,您可能会发现ABC基础结构非常有用.

  • 不要在初学者的示例代码中使用裸`except:`.它促进了不良做法. (13认同)

bad*_*adp 21

try:
  #treat object as iterable
except TypeError, e:
  #object is not actually iterable
Run Code Online (Sandbox Code Playgroud)

不要运行检查,看看你的鸭子是否真的是一只鸭子,看它是否可以迭代,把它看作是不是,如果不是就抱怨.

  • @willem:请使用timeit执行基准测试.Python异常通常比if语句更快.他们可以通过解释器稍微缩短路径. (6认同)
  • 从技术上讲,在迭代过程中,你的计算可能会抛出一个`TypeError`然后抛弃你,但基本上是的. (3认同)
  • @willem:IronPython的速度很慢(与CPython相比)异常. (2认同)
  • 一个有效的尝试:声明非常快.因此,如果您没有例外,那么try-except很快.如果您期望有许多例外,"if"可以更快. (2认同)
  • 不应该通过在`TypeError`之后添加"`as e`"而不是通过添加"`,e`"来捕获异常对象? (2认同)

Vla*_*lad 18

到目前为止我找到的最佳解决方案:

hasattr(obj, '__contains__')

它基本上检查对象是否实现了in运算符.

优点(其他解决方案都没有全部三个):

  • 它是一个表达式(作为一个lambda,而不是try ...除了变体)
  • 它(应该)由所有迭代实现,包括字符串(相对于__iter__)
  • 适用于任何Python> = 2.5

笔记:

  • "请求宽恕,而不是许可"的Python哲学不适用于例如在列表中您同时具有迭代和非迭代,并且您需要根据其类型对每个元素进行不同的处理(在try和non上处理迭代) iterables上除了工作,但它看起来对接丑陋和误导)
  • 尝试实际迭代对象的这个问题的解决方案(例如[x for obj])检查它是否可迭代可能会对大型迭代产生显着的性能损失(特别是如果你只需要迭代的前几个元素,例子),应该避免

  • 仅仅因为某些东西可以包含某些东西并不一定意味着它可以迭代.例如,用户可以检查某个点是否在3D立方体中,但是您将如何遍历此对象? (45认同)
  • 这是不正确的.迭代本身不支持__contains__,至少在Python 3.4中是这样. (12认同)
  • 很好,但为什么不使用http://stackoverflow.com/questions/1952464/in-python-how-do-i-determine-if-a-variable-is-iterable/1952481#1952481中提出的收集模块?似乎对我更有表现力. (3认同)

Rot*_*eti 16

Python 3.5开始,您可以使用标准库中的输入模块来处理类型相关的事情:

from typing import Iterable

...

if isinstance(my_item, Iterable):
    print(True)
Run Code Online (Sandbox Code Playgroud)

  • @waydegg 是的,字符串是可迭代的。 (5认同)
  • 在 Python **3.6** 中,此代码不起作用。在 **3.7** 中它确实有效。看起来它将在 **3.9** 中被[弃用](https://www.python.org/dev/peps/pep-0585/)。`typing` 用于类型检查工具(例如 **MyPy**、**PyCharm**),并且不保证此行为。我认为您的意思是从“collections.abc”导入“Iterable”类。 (2认同)

Chr*_*utz 14

你可以试试这个:

def iterable(a):
    try:
        (x for x in a)
        return True
    except TypeError:
        return False
Run Code Online (Sandbox Code Playgroud)

如果我们可以使一个迭代它的生成器(但从不使用生成器,因此它不占用空间),它是可迭代的.看起来像是一种"呃"的东西.为什么你需要首先确定一个变量是否可迭代?

  • @badp,`(x代表x中的x)只是创建一个生成器,它不会对a进行任何迭代. (5认同)
  • 尝试`(x代表x中的x)`等同于尝试`iterator = iter(a)`?或者有些情况下两者不同? (5认同)
  • @Mr_and_Mrs_D不好,如果被测试的对象是随后进行迭代的迭代器(由于无法重置其位置,它将缩短1个项目),创建垃圾生成器不会在对象上进行迭代,因为它们不会被迭代,尽管我不确定如果不能迭代,它将100%引发TypeError。 (2认同)

jbo*_*chi 13

我发现了一个很好的解决方案在这里:

isiterable = lambda obj: isinstance(obj, basestring) \
    or getattr(obj, '__iter__', False)
Run Code Online (Sandbox Code Playgroud)


Ana*_*ory 10

根据Python 2词汇表,迭代是

所有序列类型(如list,str,和tuple)和一些非序列类型,如dictfile以及你与定义任何类的对象__iter__()__getitem__()方法.Iterables可用于for循环以及需要序列的许多其他地方(zip(),map(),...).当一个可迭代对象作为参数传递给内置函数iter()时,它返回该对象的迭代器.

当然,考虑到Python的一般编码风格,基于"更容易请求宽恕而不是许可"这一事实,一般的期望是使用

try:
    for i in object_in_question:
        do_something
except TypeError:
    do_something_for_non_iterable
Run Code Online (Sandbox Code Playgroud)

但是如果你需要明确地检查它,你可以测试一个可迭代的hasattr(object_in_question, "__iter__") or hasattr(object_in_question, "__getitem__").您需要检查两者,因为strs没有__iter__方法(至少在Python 2中没有,在Python 3中它们没有)并且因为generator对象没有__getitem__方法.


fmo*_*lia 6

在我的脚本中,我经常发现定义iterable函数很方便.(现在纳入了Alfe的建议简化):

import collections

def iterable(obj):
    return isinstance(obj, collections.Iterable):
Run Code Online (Sandbox Code Playgroud)

所以你可以用非常易读的形式测试任何对象是否可以迭代

if iterable(obj):
    # act on iterable
else:
    # not iterable
Run Code Online (Sandbox Code Playgroud)

就像你对这个callable功能一样

编辑:如果您安装了numpy,您可以简单地执行:from numpy import iterable,这就像是

def iterable(obj):
    try: iter(obj)
    except: return False
    return True
Run Code Online (Sandbox Code Playgroud)

如果你没有numpy,你可以简单地实现这个代码,或上面的代码.

  • 无论什么时候你都喜欢`if x:return True`` else:return False`(```是boolean)你可以把它写成`return x`.在你的情况下`return isinstance(...)`没有任何`if`. (3认同)
  • 你应该在`except:return False`行中捕获"TypeError".抓住一切都是一种糟糕的模式. (2认同)

Sör*_*ren 5

有这样的内置函数:

from pandas.util.testing import isiterable
Run Code Online (Sandbox Code Playgroud)