Обратите внимание, что это будет работать только в том случае, если вы отбрасываете не-None
значения.
Если вы реализуете функцию генератора (то, что выиметь), так что вы заботитесь о возвращаемом значении yield
, вы можете "оттолкнуть" генератор (с помощью .send()
):
# Generator
def gen():
for val in range(10):
while True:
val = yield val
if val is None: break
# Calling code
pushed = false
f = gen()
for x in f:
print(x)
if x == 5:
print(f.send(5))
pushed = True
Здесь выповторная печать x
из цикла for
и возвращаемого значения .send()
(если вы его называете).
0
1
2
3
4
5
5 # 5 appears twice because it was pushed back
6
7
8
9
Это будет работать только при нажатиивернуться один раз.Если вы хотите отодвинуться больше, чем это, вы делаете что-то вроде:
# Generator
def gen():
for val in range(10):
while True:
val = yield val
if val is None: break
# Generator Wrapper
class Pushable:
def __init__(self, g):
self.g = g
self._next = None
def send(self, x):
if self._next is not None:
raise RuntimeError("Can't pushback twice without pulling")
self._next = self.g.send(x)
def __iter__(self):
try:
while True:
# Have to clear self._next before yielding
if self._next is not None:
(tmp, self._next) = (self._next, None)
yield tmp
else:
yield next(self.g)
except StopIteration: return
# Calling code
num_pushed = 0
f = Pushable(gen())
for x in f:
print(x)
if (x == 5) and (num_pushed in [0,1,2]):
f.send(x)
num_pushed += 1
Производит:
0
1
2
3
4
5 # Pushed back (num_pushed = 0)
5 # Pushed back (num_pushed = 1)
5 # Pushed back (num_pushed = 2)
5 # Not pushed back
6
7
8
9