Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Forkable迭代器-在Python中有它的实现吗?_Python_Sockets_Data Structures_Stream_Iterator - Fatal编程技术网

Forkable迭代器-在Python中有它的实现吗?

Forkable迭代器-在Python中有它的实现吗?,python,sockets,data-structures,stream,iterator,Python,Sockets,Data Structures,Stream,Iterator,我所说的“forkable迭代器”——它是一个具有方法fork()的常规迭代器,它创建一个新的迭代器,从原始迭代器的当前迭代点开始迭代。即使对原始迭代器进行了进一步的迭代,fork也会停留在它被fork的位置,直到它本身不会被迭代为止 我的实际用例: 我有一个套接字连接和一些通过它发送的“数据包”。连接可以在“接收者”之间共享,并且每个“包”可以寻址到某个“接收者”。“数据包”可能以无序的方式出现,因此每个“接收者”都可能为不同的“接收者”接收数据包。更重要的是,如果一个“接收者”接收到不同“接

我所说的“forkable迭代器”——它是一个具有方法
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