首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >收益内部的收益是什么?

收益内部的收益是什么?
EN

Stack Overflow用户
提问于 2019-04-30 05:44:44
回答 4查看 5.4K关注 0票数 58

考虑以下代码:

代码语言:javascript
运行
AI代码解释
复制
def mygen():
     yield (yield 1)
a = mygen()
print(next(a))
print(next(a)) 

产出产出:

代码语言:javascript
运行
AI代码解释
复制
1
None

翻译在“外部”到底做了什么?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2019-04-30 06:04:18

a是一个生成器对象。当您第一次在它上调用next时,将对主体进行求值,直到第一个yield表达式(即第一个要计算的表达式:内部表达式)。该yield生成next返回的值1,然后阻塞,直到下一个条目进入生成器。这是对next的第二次调用产生的,它不向生成器发送任何值。因此,第一个(内部) yield计算为None。该值用作外部yield的参数,它将成为对next的第二个调用的返回值。如果您第三次调用next,您将得到一个StopIteration异常。

比较使用send方法(而不是next)来更改第一个yield表达式的返回值。

代码语言:javascript
运行
AI代码解释
复制
>>> a = mygen()
>>> next(a)
1
>>> a.send(3)  # instead of next(a)
3
>>> next(a)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

编写生成器的一个更明确的方法应该是

代码语言:javascript
运行
AI代码解释
复制
def mygen():
    x = yield 1
    yield x

a = mygen()
print(a.send(None))  # outputs 1, from yield 1
print(a.send(5))     # makes yield 1 == 5, then gets 5 back from yield x
print(a.send(3))     # Raises StopIteration, as there's nothing after yield x

在Python2.5之前,yield语句在调用方和生成器之间提供单向通信;对next的调用将在下一个yield语句之前执行生成器,而yield关键字提供的值将充当next的返回值。生成器还将在yield语句的点处挂起,等待下一次对next的调用恢复。

在Python2.5中,yield语句被替换为yield表达式,生成器获得了一个send方法。send的工作原理非常类似于next,只不过它可以使用一个参数。(对于其余部分,假设next(a)等同于a.send(None))。生成器在调用send(None)之后开始执行,此时它一直执行到第一个yield,后者像以前一样返回一个值。但是,现在,表达式一直阻塞到下一次对send的调用,此时yield表达式将计算为传递给send的参数。生成器现在可以在恢复时接收值。

*没有完全被替换;kojiro的回答更详细地说明了yield语句和yield表达式之间的细微差别。

票数 53
EN

Stack Overflow用户

发布于 2019-04-30 06:11:22

yield有两种形式,表达和陈述。它们大多是相同的,但我经常在statement表单中看到它们,在那里不会使用结果。

代码语言:javascript
运行
AI代码解释
复制
def f():
    yield a thing

但是在表达式形式中,yield有一个值:

代码语言:javascript
运行
AI代码解释
复制
def f():
    y = yield a thing

在你的问题中,你使用了这两种形式:

代码语言:javascript
运行
AI代码解释
复制
def f():
    yield ( # statement
        yield 1 # expression
    )

当您在结果生成器上迭代时,首先得到内部屈服表达式的结果。

代码语言:javascript
运行
AI代码解释
复制
>>> x=f()
>>> next(x)
1

此时,内部表达式还产生了外部语句可以使用的值。

代码语言:javascript
运行
AI代码解释
复制
>>> next(x)
>>>  # None

现在你用光了发电机

代码语言:javascript
运行
AI代码解释
复制
>>> next(x)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

要了解关于语句和表达式的更多信息,在其他堆栈溢出问题中有很好的答案:Python中的表达式和语句有什么区别?

票数 28
EN

Stack Overflow用户

发布于 2019-04-30 06:03:44

代码语言:javascript
运行
AI代码解释
复制
>>> def mygen():
...     yield (yield 1)
...
>>> a = mygen()
>>>
>>> a.send(None)
1
>>> a.send(5)
5
>>> a.send(2)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration
>>>
>>>
>>>
>>> def mygen():
...     yield 1
...
>>> def mygen2():
...     yield (yield 1)
...
>>> def mygen3():
...     yield (yield (yield 1))
...
>>> a = mygen()
>>> a2 = mygen2()
>>> a3 = mygen3()
>>>
>>> a.send(None)
1
>>> a.send(0)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration
>>> a2.send(None)
1
>>> a2.send(0)
0
>>> a2.send(1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration
>>> a3.send(None)
1
>>> a3.send(0)
0
>>> a3.send(1)
1
>>> a3.send(2)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration
>>>

其他的产量只是等待一个值被传递给,生成器不仅提供数据,而且还接收数据。

代码语言:javascript
运行
AI代码解释
复制
>>> def mygen():
...     print('Wait for first input')
...     x = yield # this is what we get from send
...     print(x, 'is received')
...
>>> a = mygen()
>>> a.send(None)
Wait for first input
>>> a.send('bla')
bla is received
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration
>>>

如果得到下一个值,则yield将在继续时给出下一个值,如果它不用于给出下一个值,则用于接收下一个值。

代码语言:javascript
运行
AI代码解释
复制
>>> def mygen():
...     print('Wait for first input')
...     x = yield # this is what we get from send
...     yield x*2 # this is what we give
...
>>> a = mygen()
>>> a.send(None)
Wait for first input
>>> a.send(5)
10
>>>
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55922302

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档