Ich sehe dies nicht als häufiger Anwendungsfall, das wie der Original-Generator betrachten:
def original_gen():
for x in range(10):
should_break = yield x
if should_break:
break
Wenn der Wert von should_break
immer dann mit x
auf einig Funktionsaufruf basierend berechnet wird, warum schreibe den Generator nicht einfach so:
def processing_gen(check_f):
for x in range(10):
yield x
should_break = check_f(x)
if should_break:
break
Allerdings denke ich normalerweise an den Code, der die generierten Werte als geschrieben verarbeitet innerhalb der Schleife (sonst was ist der Punkt, um eine Schleife an allen zu haben?)
Was wirklich scheint es, was Sie tun wollen, ist ein Generator zu schaffen, wo wirklich die __next__
Aufruf der Methode impliziert send(process(LAST_VALUE))
, die mit einer Klasse implementiert werden kann:
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
dies jedoch immer noch sieht dies nicht so häufig verwendet, ich mit einer while
Schleife völlig in Ordnung sein würde, obwohl ich den .send
Anruf an der Spitze gestellt habe:
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)
Und Sie könnten, dass in einem try: ... except StopIteration:pass
wickeln, obwohl ich für einen Fehler, dass nur darauf warten, finden sich besser mit einem Kontext-Manager zum Ausdruck zu erhöhen:
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)
Nun, Sie könnten es viel kürzer machen, indem Sie versuchen/außer außerhalb der Schleife; Das wird dir eine Menge von try/exception und der if-Bedingung sparen. –
@tobias_k behoben, danke. – max