Forkable迭代器-在Python中有它的实现吗?
我所说的“forkable迭代器”——它是一个具有方法Forkable迭代器-在Python中有它的实现吗?,python,sockets,data-structures,stream,iterator,Python,Sockets,Data Structures,Stream,Iterator,我所说的“forkable迭代器”——它是一个具有方法fork()的常规迭代器,它创建一个新的迭代器,从原始迭代器的当前迭代点开始迭代。即使对原始迭代器进行了进一步的迭代,fork也会停留在它被fork的位置,直到它本身不会被迭代为止 我的实际用例: 我有一个套接字连接和一些通过它发送的“数据包”。连接可以在“接收者”之间共享,并且每个“包”可以寻址到某个“接收者”。“数据包”可能以无序的方式出现,因此每个“接收者”都可能为不同的“接收者”接收数据包。更重要的是,如果一个“接收者”接收到不同“接
fork()
的常规迭代器,它创建一个新的迭代器,从原始迭代器的当前迭代点开始迭代。即使对原始迭代器进行了进一步的迭代,fork也会停留在它被fork的位置,直到它本身不会被迭代为止
我的实际用例:
我有一个套接字连接和一些通过它发送的“数据包”。连接可以在“接收者”之间共享,并且每个“包”可以寻址到某个“接收者”。“数据包”可能以无序的方式出现,因此每个“接收者”都可能为不同的“接收者”接收数据包。更重要的是,如果一个“接收者”接收到不同“接收者”的“数据包”,那么这个“不同的接收者”必须仍然能够读取该数据包
因此,我想实现这样一个可分叉迭代器,它将表示连接,每个接收器将生成自己的分叉,读取它并搜索为它寻址的“数据包”
有人知道我所说的任何实现吗?您正在寻找:
从单个iterable返回n个独立迭代器
一定要考虑到实现将缓冲数据以服务于所有子迭代器:
此itertool可能需要大量辅助存储(取决于需要存储的临时数据量)
此外,您应该只使用返回的子迭代器;在源迭代器上迭代不会将数据传播到
tee()
iterables。这是我目前对forkable迭代器的实现:
#!/usr/bin/env python
# coding=utf-8
from collections import Iterator, deque
import threading
class ForkableIterator(Iterator):
def __init__(self, iterator, buffer=None, *args, **kwargs):
self.iterator = iter(iterator)
if buffer is None:
self.buffer = deque()
else:
self.buffer = buffer
args = iter(args)
self.refs = kwargs.get('refs', next(args, {}))
self.refs.setdefault('base', 0)
self.pointer = kwargs.get('pointer', next(args, 0))
self.lock = kwargs.get('lock', next(args, threading.Lock()))
@property
def pointer(self):
return self.refs[self] + self.refs['base']
@pointer.setter
def pointer(self, value):
self.refs[self] = value
def __del__(self):
del self.refs[self]
def __iter__(self):
return self
def next(self):
with self.lock:
if len(self.buffer) - self.pointer == 0:
elem = next(self.iterator)
self.buffer.append(elem)
else:
if self.pointer == min(self.refs.itervalues()):
elem = self.buffer.popleft()
self.refs['base'] -= 1
else:
elem = self.buffer[self.pointer]
self.pointer += 1
return elem
def fork(self):
return self.__class__(self.iterator, self.buffer,
refs=self.refs, pointer=self.pointer,
lock=self.lock)
哇,我以前没有注意到这个函数,尽管我经常使用
itertools
。我认为有可能比tee
更好的实现tee
有3个缺点-1)它使用多个列表作为临时数据,很明显,一个列表就足够了。2) 使用tee
时,您不能叉另一个叉(请参阅)。3) 对于大量的临时数据,可以选择使用自定义容器作为缓冲区(例如,它可以类似于DiskCachedList
),这是很有价值的。@GillBates 1)Python实现的文档就是一个例子;不使用单独的队列2)您正在创建更多的子代,然后推进文档明确禁止的父代3)您可以自由实施自己的专业版本。在我看来,有比使用带有磁盘缓存的tee更好的优化算法的方法。3)它们是什么?例如,对于我的用例(见正文)2)文档中没有提到双重分叉。@GillBates:3)这取决于您试图解决的问题。示例:I,而另一个答案中使用了tee
。你的案子不够具体,不能说什么,真的。2) 是的,它们会这样做:一旦tee()
进行分割,原始的iterable就不应该在其他任何地方使用。2)我说的是在从另一个tee
调用中获得的迭代器之一上调用tee
。