python - 何时使用 __iter__() 与 iter()?
问题描述
假设我有一个实现__iter__()
函数的类,是首选使用iter(obj)
还是直接调用obj.__iter__()
?除了必须使用魔法功能少输入 5 个字符之外,还有什么真正的区别吗?
相比之下:对于我来说next()
,__next__()
我可以看到使用魔法函数具有默认值的优势。
解决方案
区别主要只是方便。打字更少,阅读符号更少,阅读速度更快。但是,各种内置函数(例如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'
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>__()
(使用 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)
推荐阅读
- java - 如果是可选的,我该怎么做
不存在或存在,而是一个空字符串? - php - 如何在应用批量编辑选项(如编辑或移动到垃圾箱)时触发操作?有没有特定的钩子?
- chart.js - 是否可以在 web2py 中使用 Chart.js?
- javascript - 什么是不改变 js 原型的原因?
- javascript - indexOf() 反斜杠返回 -1 javascript
- mysql - 基于值范围的任意分组的 MySQL 方法(直方图)
- asp.net-mvc - 能否在 Azure 函数连接字符串部分同时使用测试和生产连接字符串?
- angular - Angular Router.navigate 函数只是重新加载同一页面
- dotnetnuke - 2sxc 中的多语言应用程序 - 一些想法
- c# - DoubleAnimation 不更新 Canvas.TopProperty/LeftProperty