Wizard
Wizard

Reputation: 22113

Coroutine start running from send() rather than next()

I am learning coroutine from awesome presentation by David Beazley.Coroutine

I am very confused about a simple task example in which a generator start running without a proceeding next()

class Task(object):
    taskid = 0
    def __init__(self, target):
        Task.taskid += 1
        self.tid    = Task.taskid #Task id
        self.target = target      #Target coroutine
        self.sendval = None  #value to send

    def run(self):
        return self.target.send(self.sendval)

# a very simple generator

def foo():
    print('Part 1')
    yield
    print("Part 2")
    yield

It starts without next()

In [8]: t1 = Task(foo())                                                                                          
In [9]: t1.run()                                                                                                  
Part 1

As to foo

In [10]: f1 = foo()                                                                                               

In [11]: f1.send(1)                                                                                               
TypeError: can't send non-None value to a just-started generator

It should be started with next() in advance.

How could I understand this situation?

Upvotes: 1

Views: 130

Answers (1)

user10325516
user10325516

Reputation:

Error description tells you what is wrong and what you should do - you should send None to just-created generator. That is f1.send(None) instead of f1.send(1). Ususally coroutines are used with the decorator like the one you provided in the question (class Task and its method run) or like the following one:

def coroutine(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        generator = func(*args, **kwargs)
        next(generator)
        return generator
    return wrapper

Upvotes: 1

Related Questions