【问题标题】:Coroutine start running from send() rather than next()协程从 send() 而不是 next() 开始运行
【发布时间】:2018-11-01 14:36:11
【问题描述】:

我正在从 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()开头。

我怎么能理解这种情况?

【问题讨论】:

    标签: python python-3.x coroutine


    【解决方案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
    

    【讨论】:

    • 为什么任务运行时不调用 next()
    • 它没有装饰器。
    • generator.send(None)next(generator) 的替代品。 t1 = Task(foo()) 本质上是装饰。
    • ty,我明白了。 foo() 是一个被调用的函数,看起来很奇怪的装饰。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多