python - 自定义迭代器和 itertools.tee 问题
问题描述
我的自定义迭代器应该在调用 next 时调用特定的方法。它最初以这种方式工作,但是在第二次在迭代器上调用 itertools.tee 之后,该方法不会被调用。
我实际上已经有了解决方案/解决方法,但我想了解问题的根本原因。
class MyIterator(object):
def __init__(self, elements):
self._elements = iter(elements)
def __iter__(self):
return self
def next(self):
element = (self._elements)
if isinstance(element, HwState):
element.el_method()
return element
elements = list(...)
iterator1, iterator2 = itertools.tee(MyIterator(elements))
element1 = next(iterator2) # ok
element2 = next(iterator2) # ok
iterator1, iterator2 = itertools.tee(MyIterator(iterator1))
element1 = next(iterator2) # el_method() is not called but correct element is returned
element2 = next(iterator2) # el_method() is not called but correct element is returned
我以这种方式“解决”了这个问题:
elements = list(...)
iterator = MyIterator(elements)
element1 = next(iterator)
element2 = next(iterator)
iterator = MyIterator(elements)
element1 = next(iterator) # el_method() is called, correct element is returned
element2 = next(iterator) # el_method() is called, correct element is returned
解决方案
itertools.tee
请参阅文档中包含的“大致等效”实现:
def tee(iterable, n=2):
it = iter(iterable)
deques = [collections.deque() for i in range(n)]
def gen(mydeque):
while True:
if not mydeque: # when the local deque is empty
try:
newval = next(it) # fetch a new value and
except StopIteration:
return
for d in deques: # load it to all the deques
d.append(newval)
yield mydeque.popleft()
return tuple(gen(d) for d in deques)
本质上,tee
为每个生成的迭代器保留一个队列。当请求一个新值时,如果迭代器队列中有东西,它会从那里获取下一个值,如果队列是空的,它会调用next
原始迭代器一次并将结果添加到每个队列。这意味着生成的值被“缓存”并由每个迭代器返回,而不是重复生成元素的工作。
此外,通常不可能tee
按照您的预期行事,因为tee
通常不知道如何制作迭代器的副本。例如考虑一个文本文件。一旦您原则上阅读了一行,您就不能返回(以简单的顺序访问),并且没有“复制文件迭代器”之类的东西(要模拟类似的东西,您需要多个文件处理程序或查找),所以您只需保存您阅读的行并稍后在其他迭代器中返回它们。
推荐阅读
- java - IntelliJ 无法识别某些 Spring 包
- javascript - JAVASCRIPT 只有第一个函数在我的 window.onscroll 函数上工作
- python - VMWare Workstation 升级后 Python VIX 脚本抛出异常
- ansible - 如何在ansible中显示两个不同任务寄存器变量的值
- reactjs - 如何让组件通过 handleClick 重定向?
- flutter - 仅将底部阴影颤动到容器
- r - 使用 data.table 扩展行会导致关于回收的错误
- laravel - 我想返回一个用户,其中列出了他们通过该用户名推荐的所有人员的列表
- swiftui - 在使用 ForEach 迭代 CBPeripherals 数组时,我得到了一个 CBPeer
- python-3.x - 我需要帮助来编写一个分别计算数字和字母然后以字典格式返回结果的函数