[英]How can I get “START!” to print after the first line of asterisks when I run it, rather than just the changes of direction?
[英]How can I run the initialization code for a generator function immediately, rather than at the first call?
我有一个生成器函数,它是这样的:
def mygenerator():
next_value = compute_first_value() # Costly operation
while next_value != terminating_value:
yield next_value
next_value = compute_next_value()
我希望在调用函数后立即运行初始化步骤(在 while 循环之前),而不是仅在第一次使用生成器时运行。 有什么好方法可以做到这一点?
我想这样做是因为生成器将在单独的线程(或进程,或任何多处理使用)中运行,并且我不会在短时间内使用返回,并且初始化有点昂贵,所以我想要它在我准备使用这些值时进行初始化。
我需要类似的东西。 这就是我登陆的地方。 将生成器函数推入内部并返回它的调用。
def mygenerator():
next_value = compute_first_value()
def generator():
while next_value != terminating_value:
yield next_value
next_value = compute_next(next_value)
return generator()
class mygenerator(object):
def __init__(self):
self.next_value = self.compute_first_value()
def __iter__(self):
return self
def next(self):
if self.next_value == self.terminating_value:
raise StopIteration()
return self.next_value
您可以使用itertools.chain
相当容易地创建一个“预先准备好的”迭代器:
from itertools import chain
def primed(iterable):
"""Preprimes an iterator so the first value is calculated immediately
but not returned until the first iteration
"""
itr = iter(iterable)
try:
first = next(itr) # itr.next() in Python 2
except StopIteration:
return itr
return chain([first], itr)
>>> def g():
... for i in range(5):
... print("Next called")
... yield i
...
>>> x = primed(g())
Next called
>>> for i in x: print(i)
...
0
Next called
1
Next called
2
Next called
3
Next called
4
我想你可以在第一条语句完成后产生 None ,然后在你的调用代码中:
gen = mygenerator()
next(gen) # toss the None
do_something(gen)
对于我的用例,我使用了@ncoghlan 答案的修改版本,但包装在工厂函数中来装饰生成函数:
import collections, functools, itertools
def primed_generator(generating_function):
@functools.wraps(generating_function)
def get_first_right_away_wrapper(*args,**kw):
"call the generator function, prime before returning"
gen = generating_function(*args,**kw)
assert isinstance(gen,collections.Iterator)
first_value = next(gen)
return itertools.chain((first_value,),gen)
return get_first_right_away_wrapper
然后只是装饰功能:
@primed_generator
def mygenerator():
next_value = compute_first_value() # Costly operation
while next_value != terminating_value:
yield next_value
next_value = compute_next_value()
并且会立即计算第一个值,结果是透明的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.