“究竟是什么?”;iterable“;用Python是什么意思?为什么不是';我的对象实现了一个iterable`\uuuu getitem\uuu()`吗?
首先我想澄清一下,我不是在问什么是“迭代器” 这就是术语“iterable”在Python中的定义: iterable 能够一次返回一个成员的对象。 iterables的示例包括所有序列类型(如list、str、, 和元组)和一些非序列类型,如dict、文件对象和 使用\uuuu iter\uuuuuuuuuuuuuu()或uuuu getitem\uuuuuuuuuuuu()方法定义的任何类的对象 Iterables可用于for循环和许多其他地方 需要序列的位置(zip(),map(),…)。当一个不可忍受的人 对象作为参数传递给内置函数iter(),它 返回对象的迭代器。这个迭代器适合一次遍历 在一组值上。当使用iterables时,通常不是 需要调用iter()或自己处理迭代器对象。这个 for语句会自动为您创建一个临时 未命名变量,用于在循环期间保持迭代器 另请参见迭代器、序列和生成器 例如,使用“究竟是什么?”;iterable“;用Python是什么意思?为什么不是';我的对象实现了一个iterable`\uuuu getitem\uuu()`吗?,python,iterable,Python,Iterable,首先我想澄清一下,我不是在问什么是“迭代器” 这就是术语“iterable”在Python中的定义: iterable 能够一次返回一个成员的对象。 iterables的示例包括所有序列类型(如list、str、, 和元组)和一些非序列类型,如dict、文件对象和 使用\uuuu iter\uuuuuuuuuuuuuu()或uuuu getitem\uuuuuuuuuuuu()方法定义的任何类的对象 Iterables可用于for循环和许多其他地方 需要序列的位置(zip(),map(),…)。
isinstance(e,collections.Iterable)
是检查对象是否可Iterable的最具python风格的方法。所以我用Python 3.4.3做了一些测试:
from collections.abc import Iterable
class MyTrain:
def __getitem__(self, index):
if index > 3:
raise IndexError("that's enough!")
return index
for name in MyTrain():
print(name) # 0, 1, 2, 3
print(isinstance(MyTrain(), Iterable)) # False
结果很奇怪:MyTrain
定义了\uuu getitem\uuuu
方法,但它不被视为一个iterable对象,更不用说它能够一次返回一个数字了
然后,我删除了\uuu getitem\uuuuuuuuuuu
并添加了\uuuuuuu iter\uuuuuuuuuu
方法:
from collections.abc import Iterable
class MyTrain:
def __iter__(self):
print("__iter__ called")
pass
print(isinstance(MyTrain(), Iterable)) # True
for name in MyTrain():
print(name) # TypeError: iter() returned non-iterator of type 'NoneType'
它现在被认为是一个“真正的”可编辑对象,尽管它在迭代时不能生成任何内容
那么,我是否误解了某些内容,或者文档不正确?这是一个可编辑的文档。但是,您没有从abc.Iterable继承,因此Python自然不会将其报告为该类的后代。这两件事——作为一个iterable和从基类下降——是完全不同的。
iterable
是允许对其元素进行某种迭代的东西(集合任何东西)。但是python中迭代的一般方式是什么?这就是在关键字中使用-,它使用对象的方法。因此,在这方面,任何定义的对象都可以与中的一起使用,并且是一个Iterable
因此,检查对象是否可iterable的大多数“duck-typing”方法是检查对象是否为this(是的,我隐式地知道,由于虚拟类的缘故,isinstance
案例中也发生了这种情况)
因为根据duck类型,我们关心的是对象提供的行为,而不是它的故事
如果您的\uuuu iter\uuuu
实现有错误,这并不意味着对象不可编辑,这只意味着您的代码中有错误
注意:-那些没有定义\uuu iter\uuuu
的对象在一般意义上仍然是可移植的,通过使用其他方法,只是它们不能与关键字中的一起使用。
例如:-NumberList
实例在每个方法上都是可iterable的,但在python意义上是不可iterable的
class NumberList:
def __init__(self, values):
self.values = values
def each(self):
return self.values
我认为这里的混淆点在于,尽管实现\uuuu getitem\uuuu
允许您迭代对象,但它不是由定义的接口的一部分
允许一种形式的虚拟子类化,isinstance
和issubclass
认为实现指定方法的类(在Iterable
的情况下,只有\uu iter\uuuu
)是ABC的子类,即使它们没有显式地从ABC继承。不过,它并不检查方法实现是否实际工作,只检查是否提供了方法实现
有关更多信息,请参阅,其中介绍了ABCs
使用isinstance(e,collections.Iterable)
是最具python风格的方法
检查对象是否可编辑的步骤
我不同意;我将使用并尝试在对象上迭代。如果对象不可iterable,将引发TypeError
,如果要处理不可iterable的输入,可以在函数中捕获该错误,如果不可iterable,则允许向调用方渗透。这完全回避了对象决定如何实现迭代的步骤,只是找出它是否在最合适的时间实现迭代
再补充一点,我认为你引用的文件有点误导。引用这句话,或许可以澄清这一点:
对象必须是支持迭代协议的集合对象(方法\uu iter\uu()
),或者它必须支持序列
协议(带有整数参数的\uuuu getitem\uuuu()方法
在0
)
这清楚地表明,尽管两个协议都使对象可移植,但只有一个协议是实际的“迭代协议”,并且正是这一点,isinstance(thing,iterable)
测试了它。因此,我们可以得出结论,在最普遍的情况下,检查“您可以迭代的内容”的一种方法是:
isinstance(thing, (Iterable, Sequence))
虽然这也要求您将\uuu len\uuuuuuuuuuuuuuuuuuuuu
与\uuuuu getitem\uuuuuuuuuuuuuuuu
一起实现到“虚拟子类”序列isinstance
将无法检查接口是否正确实现,但在您实际尝试对其进行迭代之前,这一点不会被发现,只是需要使用适当的方法(在本例中)是可用的。“使用isinstance(e,collections.Iterable)
是检查对象是否可Iterable的最具python风格的方法”-不,我想说尝试对其进行迭代是最具python风格的方法!要测试某个对象是否可Iterable,我需要执行一个try/except块,其中我尝试var=iter(var),如果它抛出和异常,则它不是iterable@jonrsharpe.但那
isinstance(thing, (Iterable, Sequence))