什么是yield
Python的关键字是用吗?
答复大纲/摘要
- 函数函数函数函数
yield
当呼唤,返回返回 a发电机发电机.
- 发电机是迭代器,因为它们实施动态自动交换协议这样你就可以绕过他们了
- 发电机也可以已发送信息使它在概念上成为共礼管.
- 在Python 3,你可以代表代表从一个发电机到另一个发电机,双向
yield from
.
- (附录对几个答案,包括前一个答案,并讨论使用
return
在发电机中。 )
发电机:
yield
只是在功能定义中的法律内涵,而且列入《公约》yield
在函数定义中,函数定义使其返回生成器。
发电机的构想来自其他语文(见脚注1),其实施方式各有不同。冻结当发电机被调用(方法将在下文讨论)时,恢复执行,然后冻结在下一个产地。
yield
简易的给养,执行循环协议由以下两种方法界定:__iter__
和__next__
。这两种方法都使对象成为可键入检查对象的迭代器。Iterator
基础摘要类collections
模块。
def func():
yield 'I am'
yield 'a generator!'
让我们进行一些反省:
>>> type(func) # A function with yield is still a function
<type 'function'>
>>> gen = func()
>>> type(gen) # but it returns a generator
<type 'generator'>
>>> hasattr(gen, '__iter__') # that's an iterable
True
>>> hasattr(gen, '__next__') # and with .__next__
True # implements the iterator protocol.
生成器类型是一个子迭代器类型 :
from types import GeneratorType
from collections.abc import Iterator
>>> issubclass(GeneratorType, Iterator)
True
如有必要,我们可以这样打字检查:
>>> isinstance(gen, GeneratorType)
True
>>> isinstance(gen, Iterator)
True
A. 单Iterator
即已用尽,您不能重新使用或重置它:
>>> list(gen)
['I am', 'a generator!']
>>> list(gen)
[]
如果你想再次使用其功能,你必须再做一次(见脚注2):
>>> list(func())
['I am', 'a generator!']
可以按方案生成数据,例如:
def func(an_iterable):
for item in an_iterable:
yield item
上述简单生成器也相当于以下生成器 -- -- 从Python 3.3来看,您可以使用yield from
:
def func(an_iterable):
yield from an_iterable
不过,yield from
还允许向次级发电机授权,将在下一节 " 与子大麻合作的代表团 " 中加以解释。
计票:
yield
窗体中的表达式,该表达式允许将数据发送到生成器(见脚注3)
举一个例子,请注意received
变量,该变量将指向发送到生成方的数据:
def bank_account(deposited, interest_rate):
while True:
calculated_interest = interest_rate * deposited
received = yield calculated_interest
if received:
deposited += received
>>> my_account = bank_account(1000, .05)
首先,我们必须排队 发电机与内建功能,next
。next
或__next__
方法, 取决于您使用的 Python 版本 :
>>> first_year_interest = next(my_account)
>>> first_year_interest
50.0
现在我们可以把数据传送到发电机里了发送中发送None
与调用相同next
.) :
>>> next_year_interest = my_account.send(first_year_interest + 1000)
>>> next_year_interest
102.5
合作代表团yield from
现在,回顾yield from
Python 3 提供。 这让我们可以将 共同路线 委托给子coustine :
def money_manager(expected_rate):
# must receive deposited value from .send():
under_management = yield # yield None to start.
while True:
try:
additional_investment = yield expected_rate * under_management
if additional_investment:
under_management += additional_investment
except GeneratorExit:
'''TODO: write function to send unclaimed funds to state'''
raise
finally:
'''TODO: write function to mail tax info to client'''
def investment_account(deposited, manager):
'''very simple model of an investment account that delegates to a manager'''
# must queue up manager:
next(manager) # <- same as manager.send(None)
# This is where we send the initial deposit to the manager:
manager.send(deposited)
try:
yield from manager
except GeneratorExit:
return manager.close() # delegate?
现在我们可以将功能委托给一个子生成器 并且它可以被一个发电机使用 就像上面那样:
my_manager = money_manager(.06)
my_account = investment_account(1000, my_manager)
first_year_return = next(my_account) # -> 60.0
现在模拟在账户中再增加1000, 加上账户的回报( 60.0 ) :
next_year_return = my_account.send(first_year_return + 1000)
next_year_return # 123.6
您可以阅读更多关于yield from
内PEP380号
其他方法:关闭和投掷
缩略close
方法生成GeneratorExit
功能执行被冻结时, 这也会被调用 。__del__
以便您可以设置任何清理代码, 用于处理GeneratorExit
:
my_account.close()
您也可以丢弃一个例外,该例外可在生成器中处理,或向用户传播:
import sys
try:
raise ValueError
except:
my_manager.throw(*sys.exc_info())
提高:
Traceback (most recent call last):
File "<stdin>", line 4, in <module>
File "<stdin>", line 6, in money_manager
File "<stdin>", line 2, in <module>
ValueError
结论 结论 结论 结论 结论
我认为,我已处理了下列问题的所有方面:
什么是yield
Python的关键字是用吗?
事实证明yield
我肯定我可以为此再增加更详尽的例子。如果你们想要更多或有建设性的批评,请在下面评论,让我知道。
附录:
顶级/接受的答复的优先程度**
- 它被混淆了 是什么制造了易 易 易 性,仅以列表作为示例。见以上我的引用,但摘要:a易 易 易 性具有 a 的
__iter__
返回方法返回振动器。 A. A.振动器额外提供a.__next__
方法,该方法隐含地称为:for
循环直到它升起StopIteration
,一旦它升起StopIteration
它将继续这样做。
- 然后,它用发电机表达式来描述发电机是什么。 因为发电机表达式只是创建一个振动器,它只是混淆了事情, 而我们仍然还没有达到
yield
部分。
- 内控制发电机耗竭他呼唤
.next
方法(仅在Python 2 中有效),当他应该使用内设函数时,next
调用next(obj)
这是一种适当的间接分解层,因为他的代码在Python 3号行不通。
- 这跟什么无关
yield
完全没有。
- 不讨论采用哪些方法
yield
与新功能一起提供yield from
Python 3 号的Python 3。
上方/接受的回答是一个非常不完整的回答。
答复的精度答复建议yield
中显示或理解生成方的表达或理解。
语法目前允许列表理解中的任何表达式 。
expr_stmt: testlist_star_expr (annassign | augassign (yield_expr|testlist) |
('=' (yield_expr|testlist_star_expr))*)
...
yield_expr: 'yield' [yield_arg]
yield_arg: 'from' test | testlist
由于产量是一种表达方式,有些人认为在理解或生成方表达方式中使用产量是令人感兴趣的,尽管没有提出特别好的使用方式。
CPython 核心开发者是讨论其津贴的折旧问题从邮件列表中找到一个相关的邮件 :
2017年1月30日19:05时,
2017年1月29日17:39Craig Rodrigues写道:
我不管用哪一种方法都行,把事情和在Python 3的一样丢在一边是不好的,IMHO。
我的投票是 语法错误,因为你没有得到 你期望的语法。
我同意这对我们来说是个明智的地方 因为任何依靠当前行为的守则 都太聪明了 无法维持下去
就到达那里而言,我们很可能想要:
- 3.7年的语法警告或折旧警告
- 2.7.x.x.中的Py3k警告
- 3.8 中的语法rror
干杯,尼克。
- Nick Coghlan ncoghlan at gmail.com Brisbane, 澳大利亚布里斯班
此外,还有未决问题(10544)这一点似乎指着着《公约》和《公约》从未是一个好主意(PyPy, PyPython 的 Python 执行书写在 Python 上, 已经在提高语法警告 。 )
直至CPython的开发商告诉我们:别放yield
中显示或理解生成方的表达或理解。
缩略return
生成器中的语句
内Python 3:
在发电机功能中,return
声明中表示发电机已经完成,并将导致StopIteration
返回的值(如果有的话)用作构建的论据。StopIteration
成为StopIteration.value
属性。
历史记录,Python 2: "在发电机功能中,return
不允许包含语句expression_list
在这种背景下,光return
表示发电机完成并导致StopIteration
将升起。expression_list
基本上是用逗号分隔的任意数表达式 - 基本上是在 Python 2 中, 您可以用return
,但你不能返回一个值。
脚注脚注
在向Python引入发电机概念的提案中,提到了CLU、Sather和“图标”等语言。 通常的想法是,功能可以维持内部状态,并产生用户需要的中间数据点。 这保证了这一功能能够维持内部状态,并产生中间数据点。业绩优于其他方法,包括Python线在某些系统上甚至都找不到
这意味着,例如,range
对象不是物体Iterator
i 尽管它们是可循环的, 因为它们可以被再利用。就像列表一样,它们__iter__
方法返回迭代对象。
yield
最初作为声明被引入,意思是它只能出现在代码块的线条开头。yield
创建收益表达式 。https://docs.python.org/2/reference/simple_stmts.html#grammar-token-yield_stmt这一变化是:拟议拟议拟议数允许用户像收到数据一样将数据发送到生成器中。 要发送数据, 就必须能够将数据指定给某些东西, 因此, 声明是行不通的 。