假设我有一个实现__iter__()函数的类,它是首选使用iter(obj)还是直接调用obj.__iter__()?除了要用魔法函数少键入5个字符之外,还有什么真正的区别吗?
相反,对于next()和__next__(),我可以看到使用神奇函数具有默认值的优势。
发布于 2018-11-27 16:29:13
不同之处主要在于方便。这是较少的打字,更少的符号阅读,所以更快的阅读。然而,各种内置功能(例如。iter,len等)通常会做一些小的类型检查,以便尽早捕获错误。如果您编写了一个customer __iter__方法,并且它返回了2,那么调用obj.__iter__()不会捕捉到它,但是iter(obj)会抛出一个类型错误。例如:
>>> class X:
def __iter__(self):
return 2
>>> x = X()
>>> x.__iter__()
2
>>> iter(x)
Traceback (most recent call last):
File "<pyshell#37>", line 1, in <module>
iter(x)
TypeError: iter() returned non-iterator of type 'int'iter还为没有__iter__但确实实现了序列协议的对象实现迭代器协议。也就是说,它们有一个__getitem__方法,该方法实现从索引0开始的序列,并为不受限制的索引引发IndexError。这是python的一个旧特性,并不是真正应该使用的新代码。例如:
>>> class Y:
def __getitem__(self, index):
if 0 <= index < 5:
return index ** 2
else:
raise IndexError(index)
>>> list(iter(Y())) # iter not strictly needed here
[0, 1, 4, 9, 16]什么时候应该使用__iter__?这可能与__iter__无关,但是如果您需要访问父类使用的方法的实现,那么最好以super().__<dunder_method>__()样式调用这些方法(使用Python3样式的超级用法)。例如:
>>> class BizzareList(list):
def __iter__(self):
for item in super().__iter__():
yield item * 10
>>> l = BizzareList(range(5))
>>> l # normal access
[0, 1, 2, 3, 4]
>>> l[0] # also normal access
0
>>> tuple(iter(l)) # iter not strictly needed here
(0, 10, 20, 30, 40)发布于 2021-08-25 09:16:18
iter()函数(它反过来调用iter()方法)是一个内置的python函数,从它返回一个迭代器。您可以选择使用iter(obj)或obj.__iter__(),它们只是一回事。这只是因为__iter__()是一个用户定义的函数,调用它只会执行编写的代码要求它做的事情。另一方面,调用iter()函数将反过来调用用户定义的__iter__()函数并运行相同的代码。但是,iter()还将运行内置的“类型”检查,在该检查中,如果自定义的__iter__()不返回迭代器对象,则会引发错误。* next() & __next__()也是如此。
因此,iter(obj) ~= obj.__iter__(),next(obj) ~= obj.__next__()
注意,如果对象os打算成为迭代器,则在创建类时,__iter__()和__next__()必须由用户定义。
https://stackoverflow.com/questions/53503321
复制相似问题