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



