Я знаю, что в 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
.Этот пример заставил меня понять, что, возможно, не удастся выполнить то, что я ищу, так как для этого потребуется выполнение шагов после возврата функции (может потребоваться многопоточность).