【发布时间】:2019-04-19 09:11:45
【问题描述】:
我知道在 Python 中,生成器是延迟调用的。例如:
>>> def G():
... print('this was evaluated now 1')
... yield 1
... print('this was evaluated now 2')
... yield 2
...
>>> g = G()
>>> next(g)
this was evaluated now 1
1
>>> next(g)
this was evaluated now 2
2
print('this was evaluated now 1') 行仅在第一个 next(g) 被调用后才被评估。
我想知道是否有一种简单的方法可以非懒惰地调用生成器。这意味着当调用g = G() 时,该函数将计算直到并包括第一个yield 结果在内的所有内容,而不会实际产生。然后,在第一次调用next(g) 时,将产生已经计算的结果,并且还将计算直到并包括第二个yield 结果的所有内容。以此类推。
如何做到这一点?
这是在这种非惰性方案下的预期行为:
>>> g = G()
this was evaluated now 1
>>> next(g)
1
this was evaluated now 2
>>> next(g)
2
这是一个解决方案尝试,但不起作用:
>>> class NonLazyGenerator():
... def __init__(self,G):
... self.g = G()
... self.next_value = next(self.g)
...
... def __next__(self):
... current_value = self.next_value
... try:
... self.next_value = next(self.g)
... except StopIteration:
... pass
... return current_value
...
>>> g = NonLazyGenerator(G)
this was evaluated now 1
>>> next(g)
this was evaluated now 2
1
>>> next(g)
2
这将失败,因为该值仅在 return 语句之后产生,而直到下一个 yield 的所有内容的计算发生在 return 语句之前。这个例子让我意识到它可能无法执行我正在寻找的东西,因为它需要在函数返回后执行步骤(可能需要多线程)。
【问题讨论】:
-
你为什么想要那个? Yielding 仍然会为下一个结果做计算工作,所以你什么也得不到。
-
我可以解释我为什么要这样做,但我的问题的目的不是要找到支持或反对这样做的理由,而是要了解如何做到这一点。
-
原因是我有一个函数,它的主体中有一个
yield语句,这会将函数变成一个生成器。但是,这个yield只能根据函数参数的值来访问。我希望该函数在此参数为False时充当常规函数,否则充当生成器。如果生成器会被非懒惰地评估。这将解决问题。 (当然,还有其他方法可以解决这个问题,当然,这也不一定是好的编程,但正如我所说,我目前只对问题的答案感兴趣)