假设我有一个实现__iter__()函数的类,首选使用iter(obj)还是obj.__iter__()直接调用?除了使用magic函数少输入5个字符之外,还有什么真正的区别?
相比之下:对于next()和__next__()我可以看到在magic函数中具有默认值的优点。
区别主要在于便利。它减少了打字,减少了符号的读取,因此读取速度更快。然而,各种内置函数(例如iter,len等),通常做一个小小的型早期检查,以捕获错误。如果您编写了一个客户__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'
Run Code Online (Sandbox Code Playgroud)
iter还为no的对象实现了迭代器协议__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]
Run Code Online (Sandbox Code Playgroud)
什么时候应该使用__iter__?这可能与无关紧要__iter__,但是如果您需要访问父类使用的方法的实现,则最好以样式super().__<dunder_method>__()(使用Python 3样式的超级用法)调用此类方法。例如。
>>> 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)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
317 次 |
| 最近记录: |