1276

有没有类似的方法isiterable?到目前为止,我发现的唯一解决方案是致电

hasattr(myObj, '__iter__')

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

4

22 回答 22

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

    from __future__ import print_function
    
    try:
        some_object_iterator = iter(some_object)
    except TypeError as te:
        print(some_object, 'is not iterable')
    

    iter内置检查__iter__方法或在字符串的情况下检查__getitem__方法。

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

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

    ...

    try:
       _ = (e for e in my_object)
    except TypeError:
       print my_object, 'is not iterable'
    
  3. collections模块提供了一些抽象基类,允许询问类或实例是否提供特定功能,例如:

    from collections.abc import Iterable
    
    if isinstance(e, Iterable):
        # e is iterable
    

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

于 2009-12-23T12:16:43.617 回答
647

鸭打字

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__() 方法进行迭代的类。确定对象是否可迭代的唯一可靠方法是调用iter(obj).

于 2009-12-23T12:53:38.060 回答
185

我想更深入地了解 之间的相互作用iter__iter__以及__getitem__幕后发生的事情。有了这些知识,您将能够理解为什么您能做的最好的事情就是

try:
    iter(maybe_iterable)
    print('iteration will probably work')
except TypeError:
    print('not iterable')

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

事实

  1. 如果至少满足以下条件之一,则可以o通过调用从任何对象获取迭代器: a)具有返回迭代器对象的方法。迭代器是任何带有和(Python 2:)方法的对象。b)有方法。iter(o)

    o__iter____iter____next__next

    o__getitem__

  2. 检查 or 的实例IterableSequence检查属性__iter__是不够的。

  3. 如果一个对象o实现了 only __getitem__,而不是__iter__iter(o)将构造一个迭代器,它试图从o索引 0 开始按整数索引获取项目。迭代器将捕获任何IndexError引发的(但没有其他错误)然后引发StopIteration自身。

  4. 在最一般的意义上,iter除了尝试之外,没有其他方法可以检查返回的迭代器是否正常。

  5. 如果一个对象o实现__iter__了,该iter函数将确保返回的对象__iter__是一个迭代器。如果一个对象只实现了,则没有健全性检查__getitem__

  6. __iter__获胜。如果一个对象o同时实现了__iter__and __getitem__iter(o)将调用__iter__.

  7. 如果您想让自己的对象可迭代,请始终实现该__iter__方法。

for循环

为了继续学习,您需要了解for在 Python 中使用循环时会发生什么。如果您已经知道,请随时直接跳到下一部分。

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

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

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

迭代 a DemoIterable

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

讨论和插图

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

考虑以下类:

class BasicIterable(object):
    def __getitem__(self, item):
        if item == 3:
            raise IndexError
        return item

iter使用 的实例调用BasicIterable将返回一个没有任何问题的迭代器,因为BasicIterableimplements __getitem__

>>> b = BasicIterable()
>>> iter(b)
<iterator object at 0x7f1ab216e320>

但是,重要的是要注意b不具有__iter__属性并且不被视为Iterableor的实例Sequence

>>> from collections import Iterable, Sequence
>>> hasattr(b, '__iter__')
False
>>> isinstance(b, Iterable)
False
>>> isinstance(b, Sequence)
False

这就是为什么Luciano Ramalho 的Fluent Python建议调用iter和处理潜力TypeError作为检查对象是否可迭代的最准确方法。直接引用书中的内容:

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

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

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

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

请注意,迭代器StopIteration在无法返回下一项时引发IndexError,并且引发的item == 3内容在内部处理。这就是为什么在 aBasicIterablefor循环按预期工作的原因:

>>> for x in b:
...     print(x)
...
0
1
2

这是另一个示例,以便深入了解返回的迭代器如何iter尝试按索引访问项目的概念。WrappedDict不继承自dict,这意味着实例将没有__iter__方法。

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

请注意,调用 to__getitem__被委派给dict.__getitem__方括号表示法只是简写的方法。

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

在第 4 点和第 5 点:iter在调用时检查迭代器__iter__

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

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

class FailGetitemIterable(object):
    def __getitem__(self, item):
        raise Exception

请注意,从FailIterIterable实例构造迭代器会立即失败,而从实例构造迭代器FailGetItemIterable会成功,但会在第一次调用__next__.

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

第 6 点:__iter__获胜

这个很简单。如果一个对象实现__iter__and __getitem__iter将调用__iter__. 考虑下面的类

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

    def __getitem__(self, item):
        return ['__getitem__', 'wins'][item]

以及循环实例时的输出:

>>> iwd = IterWinsDemo()
>>> for x in iwd:
...     print(x)
...
__iter__
wins

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

您可能会问自己,为什么大多数内置序列(如list实现__iter__方法)何时__getitem__就足够了。

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

    def __getitem__(self, item):
        return self._list[item]

毕竟,对上述类的实例进行迭代,它代表对__getitem__to的调用list.__getitem__(使用方括号表示法),将正常工作:

>>> wl = WrappedList(['A', 'B', 'C'])
>>> for x in wl:
...     print(x)
... 
A
B
C

您的自定义迭代应该实现的原因__iter__如下:

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

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

于 2016-04-04T16:04:01.177 回答
92

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

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

def iterable(obj):
    return isinstance(obj, Iterable)

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

def iterable(obj):
    try:
        iter(obj)
    except Exception:
        return False
    else:
        return True

我们也在我们的代码中使用了这个目的,但是我最近开始对只被认为是可迭代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'

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

>>> from collections.abc import Iterable
>>> from faker import Faker
>>> isinstance(Faker(), Iterable)
False

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

于 2020-04-10T11:24:35.117 回答
37

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

from typing import Iterable

...

if isinstance(my_item, Iterable):
    print(True)
于 2018-02-16T16:05:32.710 回答
33

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

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

于 2009-12-23T12:17:39.790 回答
23

在 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)

现在,这是否可取或实际有效,只是约定问题。如您所见,您可以将不可迭代的对象注册为 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 会自动将该类的对象识别为可迭代对象。

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

于 2009-12-23T13:35:47.977 回答
21
try:
  #treat object as iterable
except TypeError, e:
  #object is not actually iterable

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

于 2009-12-23T12:21:35.133 回答
17

你可以试试这个:

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

如果我们可以创建一个迭代它的生成器(但永远不要使用生成器,这样它就不会占用空间),它是可迭代的。似乎是“duh”之类的东西。为什么首先需要确定变量是否可迭代?

于 2009-12-23T12:21:12.017 回答
15

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

hasattr(obj, '__contains__')

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

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

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

笔记:

  • “请求宽恕,而不是许可”的 Python 哲学在例如在列表中同时具有可迭代对象和不可迭代对象并且您需要根据其类型对每个元素进行不同处理时(在尝试和非可迭代对象时处理)时效果不佳可迭代的 except可以工作,但它看起来很丑陋且具有误导性)
  • 尝试实际迭代对象(例如 [x for x in obj])以检查它是否可迭代的此问题的解决方案可能会对大型可迭代对象造成显着的性能损失(特别是如果您只需要可迭代对象的前几个元素,例如示例)并且应该避免
于 2010-11-09T16:40:45.310 回答
14

我在这里找到了一个不错的解决方案:

isiterable = lambda obj: isinstance(obj, basestring) \
    or getattr(obj, '__iter__', False)
于 2009-12-23T13:13:41.537 回答
11

根据Python 2 Glossary,可迭代对象是

所有序列类型(例如liststrtuple)和一些非序列类型,例如dictand以及您使用or方法file定义的任何类的对象。Iterables 可用于 for 循环和许多其他需要序列的地方(zip()、map()、...)。当可迭代对象作为参数传递给内置函数 iter() 时,它会返回该对象的迭代器。__iter__()__getitem__()

当然,鉴于 Python 的一般编码风格基于“请求宽恕比许可更容易”这一事实,一般的期望是使用

try:
    for i in object_in_question:
        do_something
except TypeError:
    do_something_for_non_iterable

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

于 2012-05-19T10:17:48.847 回答
8

我经常发现在我的脚本中定义一个iterable函数很方便。(现在合并了 Alfe 建议的简化):

import collections

def iterable(obj):
    return isinstance(obj, collections.Iterable):

因此您可以测试是否有任何对象可以以非常易读的形式进行迭代

if iterable(obj):
    # act on iterable
else:
    # not iterable

就像你对callable函数所做的那样

编辑:如果你安装了 numpy,你可以简单地做: from numpy import iterable,这就像

def iterable(obj):
    try: iter(obj)
    except: return False
    return True

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

于 2013-03-24T12:41:00.607 回答
5

有一个这样的内置函数:

from pandas.util.testing import isiterable
于 2016-11-11T23:49:37.753 回答
5

我总是不明白为什么 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 对象)

于 2018-08-14T16:18:03.993 回答
3
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() 将对类型字符串bytesbytearray.

  • bytesPython 3 中的对象是可迭代True == is_iterable(b"string") == is_iterable("string".encode('utf-8'))的 Python 2 中没有这种类型。
  • bytearrayPython 2 和 3 中的对象是可迭代的True == is_iterable(bytearray(b"abc"))

OPhasattr(x, '__iter__')方法将对 Python 3 中的字符串说是,而在 Python 2 中说否(无论是''orb''还是u'')。感谢@LuisMasuelli 注意到它也会让你在一辆越野车上失望__iter__

于 2016-03-22T12:46:14.583 回答
3

有很多方法可以检查对象是否可迭代:

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")
于 2021-08-25T18:52:50.657 回答
2

尊重 Python 的鸭子类型,最简单的方法是捕获错误(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())

备注

  1. 如果异常类型相同,则对象是否不可迭代或是否已实现错误无关紧要__iter__:无论如何,您将无法迭代对象。
  2. 我想我理解你的担忧:callable如果我也可以依靠鸭子打字来引发一个没有为我的对象定义的 if 的检查,那么存在AttributeError如何检查__call__,但可迭代检查不是这种情况?

    我不知道答案,但是您可以实现我(和其他用户)提供的函数,或者只是在代码中捕获异常(您在该部分的实现将与我编写的函数一样 - 只需确保隔离从其余代码中创建迭代器,以便您可以捕获异常并将其与另一个TypeError.

于 2015-11-24T15:25:40.750 回答
1

如果 object 是可迭代isiterable的,则以下代码中的func 返回。True如果它不是可迭代的返回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
于 2017-09-15T17:57:12.030 回答
1

__iter__您可以检查属性,而不是检查属性,该__len__属性由每个 python 内置迭代实现,包括字符串。

>>> hasattr(1, "__len__")
False
>>> hasattr(1.3, "__len__")
False
>>> hasattr("a", "__len__")
True
>>> hasattr([1,2,3], "__len__")
True
>>> hasattr({1,2}, "__len__")
True
>>> hasattr({"a":1}, "__len__")
True
>>> hasattr(("a", 1), "__len__")
True

由于显而易见的原因,不可迭代的对象不会实现这一点。但是,它不会捕获没有实现它的用户定义的可迭代对象,也不会捕获iter可以处理的生成器表达式。然而,这可以在一行中完成,并且添加一个简单的or表达式检查生成器将解决这个问题。(请注意,写作type(my_generator_expression) == generator会引发NameError. 请参阅答案。)

您可以从类型中使用 GeneratorType:

>>> import types
>>> types.GeneratorType
<class 'generator'>
>>> gen = (i for i in range(10))
>>> isinstance(gen, types.GeneratorType)
True

--- utdemir 接受的答案

(这对于检查您是否可以调用len该对象非常有用。)

于 2018-08-14T08:25:19.400 回答
1

不是真的“正确”,但可以快速检查最常见的类型,如字符串、元组、浮点数等......

>>> '__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
于 2019-01-25T15:41:20.657 回答
0

派对有点晚了,但我问自己这个问题,看到这个然后想到了一个答案。不知道有没有人发过这个。但本质上,我注意到所有可迭代类型的字典中都有__getitem__()。这就是您无需尝试即可检查对象是否为可迭代对象的方式。(双关语)

def is_attr(arg):
    return '__getitem__' in dir(arg)
于 2019-08-01T22:38:03.620 回答