python-3.x - 为什么 Python 迭代器需要一个 dunder iter 函数?
问题描述
根据文档,需要可迭代的容器应该提供一个__iter__()
函数来返回一个迭代器。迭代器本身需要遵循迭代器协议,这意味着它必须提供__iter__()
返回自身、__next__()
提供下一项或引发StopIterator
异常的内容。
现在我明白了为什么在进行自己的迭代的容器中需要这两者,因为您必须同时提供迭代器和下一个项目:
class ObjAndIter:
def __init__(self):
pass
def __iter__(self):
return self
def __next__(self):
# return something intelligent or raise StopIterator
for i in ObjAndIter():
pass
但是,在迭代器是不同类型的情况下,我看不到迭代迭代器本身的用例。考虑一个(人为的)类,它只提供一个迭代器以从给定数字向上计数到某个限制:
class MyObj:
class MyIter:
def __init__(self, start, end):
self._num = start - 1
self._end = end
def __next__(self):
self._num += 1
if self._num > self._end:
raise StopIteration
return self._num
#def __iter__(self): # This is apparently required but
# return self # it runs fine without it.
def __init__(self, start, end):
self._start = start
self._end = end
def __iter__(self):
return self.MyIter(self._start, self._end)
x = MyObj(5, 10)
for i in x:
print(i)
现在这似乎适用于以下情况:
x = MyObj(5, 10)
for i in x:
print(i)
尽管迭代器不遵循迭代器协议 - 它提供__next__()
但不提供__iter__()
. 该__iter__()
函数仅在容器上调用,并且__next__()
仅在迭代器上调用。
现在如果没有迭代器 __iter__()
函数,我发现您将无法执行以下操作:
x = MyObj(5, 10)
xiter = x.__iter__()
for i in xiter:
print(i)
但是我很难想象何时需要在迭代器(而不是容器)上创建迭代器。
所以我的问题是这个。在什么情况下我需要这样做?没有它,迭代器协议似乎毫无意义,除非容器必须提供__iter__()
并且迭代器必须提供__next__()
。
顺便说一句,我已经看到了这个问题及其答案,但它们似乎没有涵盖为什么迭代器需要是可迭代的。我可以很好地看到它使代码更容易迭代容器和迭代器,但这个问题是关于为什么后者甚至是必要的。
解决方案
迭代器需要可迭代以支持 for 循环和 iter()。
这导致:为什么要迭代迭代器?
因为有时您会直接获得迭代器,例如打开的文件或生成器函数:
>>> def gen():
... yield 1
... yield 2
...
>>> it = gen()
>>> hasattr(it, '__next__')
True
这导致:为什么 Python 的某些部分返回一个 interator 而不是 iterable?
这是一种判断事物“不可倒带”/“一次性迭代”的方式。因为返回一个可迭代对象会说“您可以在其上调用 iter() 两次以对其进行两次迭代”,这是错误的。
推荐阅读
- excel - 如何让 Application.SendKeys "{TAB}" 运行?我正在尝试在表单填写应用程序中使用它
- unit-testing - Kafka Streams:流线程未能锁定状态目录
- java - 无法与 Vertx 服务器和客户端创建 SSL 连接
- android - 升级到最新的 SDK 版本 1.20.4 后运行/调试 Flutter 应用程序非常慢
- postgresql - PostgreSQL 中表的单独输入/输出类型
- command-line - 如何使用 jq 命令从文件内容创建表
- python - 谷歌分析 api 每次都崩溃
- sql - 连续编号的值组(包括重复)
- java - Java 编译器只考虑第一个数字
- angular - 设置多个验证器 - Angular Reactive Form