我认为此处的困惑点在于,尽管实现__getitem__
确实 允许您迭代对象,但它不是定义的接口的一部分Iterable
。
该抽象基类允许虚拟的子类,其中实现了指定的方法(在的情况下,类的形式Iterable
,只__iter__
),被认为是由isinstance
和issubclass
是的ABC的子类,即使他们没有明确地从他们继承 。但是,它不会检查方法实现是否 真正有效 ,而只是检查是否提供了方法实现。
有关更多信息,请参阅介绍ABC的PEP-3119。
使用isinstance(e, collections.Iterable)
是检查对象是否可迭代的最pythonic方法
我不同意; 我会用鸭式打字,只是 。如果对象不是可迭代的,TypeError
则将引发,如果您要处理不可迭代的输入,则可以捕获函数;如果不可以,则允许渗透到调用者。这完全避开了对象决定执行迭代的方式,只是找出它是否在最合适的时间执行。
要补充一点,我认为您引用的文档 有些 误导。引用iter
docs,也许可以解决这个问题:
object 必须是支持迭代协议(该__iter__()
方法)的集合对象,或者它必须支持序列协议(以__getitem__()
开头的整数参数的方法0
)。
这清楚地表明,尽管两种协议都使对象可迭代,但是只有一个是实际的 “迭代协议” ,并且正是要isinstance(thing, Iterable)
测试的对象。因此,我们可以得出结论,在最一般的情况下,一种检查 “可以迭代的事物” 的方法是:
isinstance(thing, (Iterable, Sequence))
尽管这还需要你来实现__len__
沿__getitem__
到 “虚拟子类” Sequence
。