2013-09-04 3 views
8

sto cercando coroutine una condotta secondo http://www.dabeaz.com/coroutines/Coroutines.pdfCome ottenere valore restituito da coroutine in python

La domanda è: come posso ottenere valore dalla sink, piuttosto che solo stamparlo?

Prendete questo codice per esempio

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()) 

Con questo codice ottengo:

>>> pipe.send(10) 
100 

Poi voglio ottenere il valore di ritorno, piuttosto che stamparlo, cerco di cedere da lavandino:

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

Ma sembra non funzionare, pipe.send(10) restituisce ancora None anziché un Generatore.

Quindi, come posso ottenere il valore restituito?

risposta

1

Perché il pipe.send deve restituire un generatore? E cosa hai intenzione di fare con il valore restituito?

Qualunque cosa sia, dovrebbe essere fatto in sink.

Si potrebbe, tuttavia, modificare le funzioni per

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

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

per ottenere il valore di prodotti da target, quindi pipe.send(10) sarà solo tornare 100 invece di stamparlo.

Ma ora si mescolano il produttore e il consumatore, che potenzialmente vi darà un po 'di mal di testa.


In risposta al tuo commento:

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

Dire se spingo di valore A e il valore B, dopo il filtro, la trasmissione, l'elaborazione etc, Un generato 10 valori di affondare, e B generato 8 valori affondare. E voglio il valore massimo da A e il valore massimo da B, ma come dovrei dire quale valore generato da A o da B? Qualche idea su come farlo nel lavandino? – lxyu

+0

@lxyu È possibile inviare una chiave per sapere quale produttore ha prodotto un valore e il sink potrebbe avere uno stato per sapere quali valori vengono inviati e quale valore è il valore massimo. Vedi la mia modifica. – sloth

+0

Suggerisco di inviare un oggetto che incapsula tutti i dati di cui hai bisogno! – Cucu