协程从send()开始而不是next()运行

时间:2018-11-01 14:36:12

标签: python python-3.x coroutine

我正在从David Beazley的精彩演讲中学习协程。Coroutine

我对一个简单的任务示例非常困惑,在该示例中,生成器开始运行而没有继续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

它开始时没有next()

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

关于foo

In [10]: f1 = foo()                                                                                               

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

它应该事先以next()开始。

我如何理解这种情况?

1 个答案:

答案 0 :(得分:1)

错误描述会告诉您什么地方出了问题以及您应该怎么做-您应该将None发送给刚刚创建的生成器。那是f1.send(None)而不是f1.send(1)。通常,协程与装饰器一起使用,就像您在问题中提供的装饰器(类Task及其方法run)或以下装饰器一样:

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