2013-09-04 9 views
8

Ich versuche Koroutinen Pipeline nach http://www.dabeaz.com/coroutines/Coroutines.pdfWie Rückgabewert von Koroutine in Python

Die Frage ist, erhalten, wie kann ich Wert aus den sink bekommen und nicht nur gedruckt werden?

Nehmen Sie diesen Code zum Beispiel

def coroutine(func): 
    def start(*args, **kwargs): 
     cr = func(*args, **kwargs) 
     next(cr) 
     return cr 
    return start 


@coroutine 
def produce(target): 
    while True: 
     n = (yield) 
     target.send(n*10) 


@coroutine 
def sink(): 
    try: 
     while True: 
      n = (yield) 
      print(n) 
    except GeneratorExit: 
     pass 


sk = sink() 
pipe = produce(sink()) 

Mit diesem Code bekomme ich:

>>> pipe.send(10) 
100 

Dann will ich lieber den Rückgabewert bekommen, als es zu drucken, ich versuche, von Waschbecken zu ergeben:

Aber es scheint nicht funktioniert, pipe.send(10) gibt immer noch None statt a Generator.

Also wie soll ich den Rückgabewert bekommen?

Antwort

1

Warum sollte pipe.send einen Generator zurückgeben? Und was wirst du mit dem zurückgegebenen Wert machen?

Was auch immer es ist, sollte es in sink getan werden.

Sie könnten jedoch Ihre Funktionen ändern zu

@coroutine 
def produce(target): 
    while True: 
     n = (yield) 
     yield target.send(n*10) 

@coroutine 
def sink(): 
    try: 
     while True: 
      yield (yield) 
    except GeneratorExit: 
     pass 

den Wert von target nachgegeben zu ergeben, so wird pipe.send(10) nur 100 zurückkehren, anstatt sie zu drucken.

Aber jetzt mischen Sie den Hersteller und den Verbraucher, der Ihnen möglicherweise einige Kopfschmerzen geben wird.


In Reaktion auf Ihre Anmerkung:

from collections import defaultdict 

def coroutine(func): 
    def start(*args, **kwargs): 
     cr = func(*args, **kwargs) 
     next(cr) 
     return cr 
    return start 

@coroutine 
def produce(key, target): 
    while True: 
     n = (yield) 
     target.send((key, n*10)) 

class Sink(object): 

    def __init__(self): 
     self.d = defaultdict(lambda: None) 
     self.co = self.sink() 

    def send(self, *args): 
     self.co.send(*args) 

    @coroutine 
    def sink(self): 
     try: 
      while True: 
       key, n = yield 
       self.d[key] = max(self.d[key], n) 
     except GeneratorExit: 
      pass 


sk = Sink() 
pipeA = produce("A", sk) 
pipeB = produce("B", sk) 

pipeA.send(10) 
pipeA.send(20) 
pipeA.send(40) 

pipeB.send(20) 
pipeB.send(40) 
pipeB.send(60) 

print sk.d.items() # [('A', 400), ('B', 600)] 
+0

sagen, wenn ich im Wert A und Wert B drücken, nach dem Filter, Verstreuen, Verarbeitung usw., erzeugen A 10 Werte zu sinken, und B 8 erzeugten Werte sinken. Und ich will den maximalen Wert von A und den maximalen Wert von B, aber wie soll ich sagen, welcher Wert von A oder von B erzeugt wird? Irgendeine Idee, wie man es in der Spüle macht? – lxyu

+0

@lxyu Sie können einen Schlüssel senden, um zu erfahren, welcher Produzent einen Wert erzeugt hat, und die Senke könnte einen Status haben, um zu wissen, welche Werte gesendet wurden und welcher Wert der Maximalwert ist. Siehe meine Bearbeitung. – sloth

+0

Ich schlage vor, ein Objekt zu senden, das alle Daten enthält, die Sie benötigen! – Cucu