我有两个函数,它们都将迭代器作为输入。有没有办法编写一个我可以作为输入提供给两个函数的生成器,这不需要reset
或第二次通过?我想对数据进行一次传递,但是将输出提供给两个函数:示例:
def my_generator(data):
for row in data:
yield row
gen = my_generator(data)
func1(gen)
func2(gen)
我知道我可以有两个不同的生成器实例,或者在函数之间有reset
,但是想知道是否有办法避免对数据进行两次传递。请注意,func1 / func2本身不是生成器,这很好,因为我可以有一个管道。
这里的要点是尽量避免对数据进行第二次传递。
答案 0 :(得分:3)
Python有一个非常方便的功能目录。您可以在itertools中找到与迭代器相关的内容:
import itertools
def my_generator(data):
for row in data:
yield row
gen = my_generator(data)
gen1, gen2 = itertools.tee(gen)
func1(gen1)
func2(gen2)
但是,只有func1
和func2
不消耗所有元素才有意义,因为itertools.tee()
必须记住gen
中的所有元素直到使用gen2
。
要解决此问题,请一次只使用几个元素。或者更改func1
以致电func2
。或者甚至可以将func1
更改为一个惰性生成器,它返回输入并将其输入func2
。
答案 1 :(得分:3)
您可以缓存生成器结果列表,或 重置生成器,以将数据传递到class Test {
public static void main(String[] args) {
double result = Math.pow(4 , 2);
System.out.println(result);
}
}
。问题是,如果一个有2个循环,则需要迭代数据两次,因此要么再次加载数据并创建生成器,要么缓存整个结果。
像func2
这样的解决方案也只会创建2个迭代,这与在第一次迭代后重置生成器基本相同。当然它是语法糖,但它不会改变后台的情况。
如果此处有大数据,则必须合并itertools.tee
和func1
。
func2
在实践中,设计这样的代码是一个好主意,因此可以完全控制迭代过程,并且可以使用单个迭代关联/组合映射和过滤器。
答案 2 :(得分:3)
如果使用线程是一个选项,则生成器可以只消耗一次,而不必在对消费者的调用之间存储可能不可预测的数量的产生值。以下示例以锁定步骤运行使用者;此实现需要Python 3.2或更高版本:
import threading
def generator():
for x in range(10):
print('generating {}'.format(x))
yield x
def tee(iterable, n=2):
barrier = threading.Barrier(n)
state = dict(value=None, stop_iteration=False)
def repeat():
while True:
if barrier.wait() == 0:
try:
state.update(value=next(iterable))
except StopIteration:
state.update(stop_iteration=True)
barrier.wait()
if state['stop_iteration']:
break
yield state['value']
return tuple(repeat() for i in range(n))
def func1(iterable):
for x in iterable:
print('func1 consuming {}'.format(x))
def func2(iterable):
for x in iterable:
print('func2 consuming {}'.format(x))
gen1, gen2 = tee(generator(), 2)
thread1 = threading.Thread(target=func1, args=(gen1,))
thread1.start()
thread2 = threading.Thread(target=func2, args=(gen2,))
thread2.start()
thread1.join()
thread2.join()