Python生成器发送功能的目的?

2024-06-01 07:15:38 发布

您现在位置:Python中文网/ 问答频道 /正文

有人能给我一个例子说明为什么与Python generator函数相关联的“send”函数存在吗?我完全理解屈服函数。但是,send函数让我很困惑。关于该方法的文档是复杂的:

generator.send(value)

Resumes the execution and “sends” a value into the generator function. The value argument becomes the result of the current yield expression. The send() method returns the next value yielded by the generator, or raises StopIteration if the generator exits without yielding another value.

那是什么意思?我以为价值是函数的输入?短语“send()方法返回生成器生成的下一个值”似乎也是yield函数的确切用途;yield返回生成器生成的下一个值。。。

有人能给我一个例子,一个发电机利用发送,完成一些产量不能?


Tags: andthe方法函数文档sendvaluegenerator
3条回答

这可能有帮助。这是一个不受send函数影响的生成器。它在实例化时接受number参数,不受send的影响:

>>> def double_number(number):
...     while True:
...         number *=2 
...         yield number
... 
>>> c = double_number(4)
>>> c.send(None)
8
>>> c.next()
16
>>> c.next()
32
>>> c.send(8)
64
>>> c.send(8)
128
>>> c.send(8)
256

下面是如何使用send执行相同类型的函数,因此在每次迭代中,都可以更改number的值:

def double_number(number):
    while True:
        number *= 2
        number = yield number

如下所示,您可以看到发送数字的新值会更改结果:

>>> def double_number(number):
...     while True:
...         number *= 2
...         number = yield number
...
>>> c = double_number(4)
>>> 
>>> c.send(None)
8
>>> c.send(5) #10
10
>>> c.send(1500) #3000
3000
>>> c.send(3) #6
6

您也可以将其放入for循环中,如下所示:

for x in range(10):
    n = c.send(n)
    print n

有关更多帮助,请查看此great tutorial

此函数用于编写协同程序

def coroutine():
    for i in range(1, 10):
        print("From generator {}".format((yield i)))
c = coroutine()
c.send(None)
try:
    while True:
        print("From user {}".format(c.send(1)))
except StopIteration: pass

印刷品

From generator 1
From user 2
From generator 1
From user 3
From generator 1
From user 4
...

看看控制是如何来回传递的?那是联程旅行。它们可以用于各种很酷的东西,比如异步IO和类似的东西。

想象一下,有发电机却没有信号,这是条单行道

==========       yield      ========
Generator |   ------------> | User |
==========                  ========

但是有了send,它就变成了一条双向的街道

==========       yield       ========
Generator |   ------------>  | User |
==========    <------------  ========
                  send

这为用户打开了一扇大门,用户可以动态定制生成器行为和生成器响应用户。

它用于将值发送到刚刚生成的生成器中。下面是一个人工的(非有用的)解释性例子:

>>> def double_inputs():
...     while True:
...         x = yield
...         yield x * 2
...
>>> gen = double_inputs()
>>> next(gen)       # run up to the first yield
>>> gen.send(10)    # goes into 'x' variable
20
>>> next(gen)       # run up to the next yield
>>> gen.send(6)     # goes into 'x' again
12
>>> next(gen)       # run up to the next yield
>>> gen.send(94.3)  # goes into 'x' again
188.5999999999999

你不能只用yield就这么做。

至于为什么它是有用的,我见过的最好的用例之一是Twisted的@defer.inlineCallbacks。实际上,它允许您编写这样的函数:

@defer.inlineCallbacks
def doStuff():
    result = yield takesTwoSeconds()
    nextResult = yield takesTenSeconds(result * 10)
    defer.returnValue(nextResult / 10)

结果是takesTwoSeconds()返回一个Deferred,这是一个承诺稍后将计算一个值的值。Twisted可以在另一个线程中运行计算。当计算完成时,它将其传递给deferred,然后将值发送回doStuff()函数。因此doStuff()最终看起来或多或少像一个普通的过程函数,除了它可以进行各种计算和回调等

def doStuff():
    returnDeferred = defer.Deferred()
    def gotNextResult(nextResult):
        returnDeferred.callback(nextResult / 10)
    def gotResult(result):
        takesTenSeconds(result * 10).addCallback(gotNextResult)
    takesTwoSeconds().addCallback(gotResult)
    return returnDeferred

它更加复杂和笨拙。

相关问题 更多 >