Я не считаю это частым вариантом использования, считайте это исходным генератором:
def original_gen():
for x in range(10):
should_break = yield x
if should_break:
break
Если значение should_break
всегда вычисляется на основе вызова какой-либо функции с x
, то почему бы просто не написать генератор следующим образом:
def processing_gen(check_f):
for x in range(10):
yield x
should_break = check_f(x)
if should_break:
break
Однако я обычно думаю о коде, который обрабатывает сгенерированные значения, как о написанном внутри цикла (иначе какой смысл вообще иметь цикл?)
На самом деле кажется, что вы хотите создать генератор, в котором вызов метода __next__
действительно подразумевает send(process(LAST_VALUE))
, который можно реализовать с помощью класса:
class Followup_generator(): #feel free to use a better name
def __init__(self,generator,following_function):
self.gen = generator
self.process_f = following_function
def __iter__(self):
return self
def __next__(self):
if hasattr(self,"last_value"):
return self.send(self.process_f(self.last_value))
else:
self.last_value = next(self.gen)
return self.last_value
def send(self,arg):
self.last_value = self.gen.send(arg)
return self.last_value
def __getattr__(self,attr):
"forward other lookups to the generator (.throw etc.)"
return getattr(self.gen, attr)
# call signature is the exact same as @tobias_k's checking_generator
traversal = Followup_generator(bfs(g, start_node), process)
for n in traversal:
print(n)
n = traversal.send(DATA) #you'd be able to send extra values to it
Однако это по-прежнему не так часто используется, я бы прекрасно справился с циклом while
, хотя я бы поместил вызов .send
вверху:
traversal = bfs(g, start_node)
send_value = None
while True:
n = traversal.send(send_value)
#code for loop, ending in calculating the next send_value
send_value = process(n)
И вы можете обернуть это в try: ... except StopIteration:pass
, хотя я считаю, что простое ожидание возникновения ошибки лучше выражается с помощью менеджера контекста:
class Catch:
def __init__(self,exc_type):
if issubclass(exc_type,BaseException):
self.catch_type = exc_type
else:
raise TypeError("can only catch Exceptions")
def __enter__(self):
return self
def __exit__(self,exc_type,err, tb):
if issubclass(exc_type, self.catch_type):
self.err = err
return True
with Catch(StopIteration):
traversal = bfs(g, start_node)
send_value = None
while True:
n = traversal.send(send_value)
#code for loop, ending in calculating the next send_value
send_value = process(n)
person
Tadhg McDonald-Jensen
schedule
26.04.2016