python - 基于 for 的语法跳过对“iter”的调用
问题描述
考虑以下迭代器:
class MyIterator:
def __iter__(self):
print("Calling `__iter__`")
return self
def __reversed__(self):
print("Calling `__reversed__`")
return self
def __next__(self):
print("Calling `__next__`")
raise StopIteration
for
以下代码是否存在基于 - 的等效语法:
R = reversed(MyIterator())
while True:
try:
next(R)
except StopIteration:
break
实际上打印
Calling `__reversed__`
Calling `__next__`
for
语法似乎总是添加对 的调用iter
,即使给定的对象已经遵守 Iterator 协议。
解决方案
隐式调用__iter__
是故意的;for
不知道它是否被交给了一个 itera tor或一个 itera ble,并且需要无条件地确保它有一个 itera tor,它通过调用__iter__
. 如果您的对象已经是一个迭代器,__iter__
则应该是幂等的,除了返回自身之外什么都不做(主体应该只是return self
)。在现有的 Python 代码中有一些测试通过 testing 来检测迭代器iter(x) is x
,如果你违反了规则而不是返回self
自定义迭代器,你应对不当行为负责。
关键是,你想做的事情没有意义。要么写一个可迭代的(没有 a__next__
和 a__iter__
返回一个新的迭代器)或者写一个迭代器,但是如果你写一个迭代器,你需要遵守迭代器的规则。
为了清楚起见,这里不可避免的操作顺序是:
reversed
invokes__reversed__
,理论上应该返回一个新的反向迭代器(让它返回现有的,理论上的正向迭代器是非常奇怪的)for
__iter__
隐式调用任何reversed
返回以确保它是一个迭代器(如果__reversed__
实现得当,它会返回一个全新的迭代器,但是,你最终会调用__iter__
同一个对象)for
然后__next__
为每个项目隐式调用,直到StopIteration
引发
要修复它,请__reversed__
返回一个新的反向迭代器,而不是self
; 新的迭代器__iter__
仍然会被调用,但它不会是原始迭代器上的那个。更好的是,拆分你的实现;可逆的东西首先不应该是迭代器。只需 make__iter__
和__reversed__
两个生成器函数产生它们应该产生的任何东西,并摆脱__next__
,以使您的类可迭代和可逆,但不是迭代器。
推荐阅读
- javascript - json lottie 的编辑器颜色
- google-apps-script - 在谷歌应用脚本上测量我当前的使用消耗
- sql-server - SQL Server 连接读取超时
- swiftui - SwiftUI:使用计时器更新模型并将其反映在 UI 中
- python - Pygame 窗口仅在“无响应”时响应
- arrays - 如何从 iOS Swift 中的 json 获取价值?
- python - 计算 Pandas 列中值的 3 个月滚动计数
- apache - 访问 URL 的用户会两次附加上下文路径
- java - 需要帮忙。此代码删除除索引 0 以外的所有内容
- neo4j - 遍历对象列表并通过对象 Neo4j 的属性创建节点