我所说的"可分叉迭代器"是指一个带有方法fork()
的常规迭代器,它创建了一个新的迭代器从原始迭代器的当前迭代点开始迭代。即使原始迭代器被进一步迭代,fork也会停留在它被分叉的地方,直到它本身不会被迭代为止。
我的实际用例:我有一个套接字连接,还有一些通过它发送的"数据包"。连接可以在"接收器"之间共享,每个"包"都可以寻址到某个"接收器"。"数据包"可以以无序的方式出现,因此每个"接收器"都可能接收不同"接收器"的数据包。更重要的是,如果一个"接收器"接收到不同"接收器"的"数据包",这个"不同的接收器"必须仍然能够读取该数据包。
因此,我想实现这样的可分叉迭代器,它将代表连接,每个接收器将制作自己的分叉,读取它并搜索为它寻址的"数据包"
有人知道我所说的任何实现吗?
您正在寻找itertools.tee()
函数:
从单个可迭代项返回n独立迭代器。
请考虑实现将缓冲数据以服务于所有子迭代器:
这个迭代工具可能需要大量的辅助存储(取决于需要存储多少临时数据)。
此外,您应该只使用返回的子迭代器;对源迭代器进行迭代将不会将数据传播到tee()
可迭代项。
这是我目前实现的可分叉迭代器:
#!/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)