Generator - How to get return value from coroutine in python

De openkb
Aller à : Navigation, rechercher

Sommaire

Questions

http://www.dabeaz.com/coroutines/Coroutines.pdf http://www.dabeaz.com/coroutines/Coroutines.pdf

The question is, how can I get value from the sink rather than only print it?

Take this code for example

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

With this code I get:

>>> pipe.send(10)
100

Then I want to get the return value rather than print it, I try to yield from sink:

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

But it seems not working, pipe.send(10) still returns None rather than a generator.

So how shall I get the return value?

Answers

Why should pipe.send return a generator? And what are you going to do with the returned value?

Whatever it is, it should be done in sink.

You could, however, change your functions to

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

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

to yield the value yielded by target, so pipe.send(10) will just return 100 instead of printing it.

But now you mix the producer and the consumer, which will potentially give you some headache.


In response to your comment:

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

Source

License : cc by-sa 3.0

http://stackoverflow.com/questions/18611142/how-to-get-return-value-from-coroutine-in-python

Related

Outils personnels
Espaces de noms

Variantes
Actions
Navigation
Outils