何为使用yieldPython 中的关键字?

比如说,我在试着理解这个代码1:

def _get_child_candidates(self, distance, min_dist, max_dist):
    if self._leftchild and distance - max_dist < self._median:
        yield self._leftchild
    if self._rightchild and distance + max_dist >= self._median:
        yield self._rightchild  

这就是打电话的人:

result, candidates = [], [self]
while candidates:
    node = candidates.pop()
    distance = node._get_dist(obj)
    if distance <= max_dist and distance >= min_dist:
        result.extend(node._values)
    candidates.extend(node._get_child_candidates(distance, min_dist, max_dist))
return result

当方法_get_child_candidates是否调用 ? 列表是否返回 ? 单元素 ? 是否又调用 ? 以后的呼叫何时停止 ?


1. 本代码由Jochen Schulz(jrschulz)编写,他为公制空间制作了一个伟大的Python图书馆。模块 m 空间.

当前回答

这是关于什么的心理形象yield确实如此。

我想把一条线视为有堆叠(即使它不是用这种方式执行的)。

当调用一个普通函数时, 它会将其本地变量放入堆栈, 进行一些计算, 然后清除堆栈和返回。 其本地变量的值再也不会被看到 。

yield函数,当其代码开始运行时(即函数被调用后,返回一个生成对象,该生成对象next()然后引用方法),它同样将其本地变量放在堆叠上,并计算一段时间。但是当它击中yield语句,在清理其部分堆叠并返回之前,它先对本地变量进行速记,然后将其存储在生成器对象中。它还写下它目前在其代码中的位置(即特定yield声明))

所以这是一种冷冻功能 发电机挂在了上面

何时next()函数随后被调用, 它从堆叠上取回函数的物品, 并重新激活它。 函数继续从剩余部分进行计算, 忽略了它刚刚在冷藏中度过了永恒时间的事实 。

比较以下实例:

def normalFunction():
    return
    if False:
        pass

def yielderFunction():
    return
    if False:
        yield 12

当我们调用第二个函数时,它的行为与第一个功能非常不同。yield声明可能无法取得, 但如果它存在任何地方, 它会改变我们所处理的事物的性质。

>>> yielderFunction()
<generator object yielderFunction at 0x07742D28>

电 电 电yielderFunction()(也许用它来命名这种东西是个好主意)yielder可读性前缀。 )

>>> gen = yielderFunction()
>>> dir(gen)
['__class__',
 ...
 '__iter__',    #Returns gen itself, to make it work uniformly with containers
 ...            #when given to a for loop. (Containers return an iterator instead.)
 'close',
 'gi_code',
 'gi_frame',
 'gi_running',
 'next',        #The method that runs the function's body.
 'send',
 'throw']

缩略gi_codegi_frame字段中存储冻结状态的字段。dir(..),我们可以确认 我们的心理模式 上面是可信的。

其他回答

理解什么yield确实,你必须明白什么是发电机发电机。在您能够理解发电机之前,您必须理解易可动的.

易变性

创建列表时,您可以逐项阅读其项目。逐项阅读其项目被称为迭代:

>>> mylist = [1, 2, 3]
>>> for i in mylist:
...    print(i)
1
2
3

mylist易 易 易 性。当您使用对列表的理解时,会创建列表,因此,可以循环:

>>> mylist = [x*x for x in range(3)]
>>> for i in mylist:
...    print(i)
0
1
4

能够使用的一切 " 。for... in..."是可循环的;lists, strings文档...

这些可替换的功能是实用的,因为您可以随心所欲地阅读,但您将所有值都存储在记忆中,当您拥有很多值时,这并不总是你想要的。

发电机发电机

发电机是迭代器,是一种可循环的您只能循环一次。发电机不会存储所有值的内存,它们会在飞上生成值:

>>> mygenerator = (x*x for x in range(3))
>>> for i in mygenerator:
...    print(i)
0
1
4

除了你用过的一样()代替[]但是,你,你无法不能表现 表现表现for i in mygenerator第二次,因为发电机只能使用一次:它们计算0,然后忘记它,计算1,最后计算4,一个一个。

产量d

yield是一个关键字,它被像return,但该函数将返回一个发电机。

>>> def create_generator():
...    mylist = range(3)
...    for i in mylist:
...        yield i*i
...
>>> mygenerator = create_generator() # create a generator
>>> print(mygenerator) # mygenerator is an object!
<generator object create_generator at 0xb7555c34>
>>> for i in mygenerator:
...     print(i)
0
1
4

这是一个毫无用处的例子, 但当你知道你的功能会返回 一大堆的值时, 它就方便了, 你只需要读一次。

师傅yield你必须明白当您调用函数时,函数体中的代码不会运行。函数只返回生成对象, 这有点棘手 。

然后,你的代码会继续 从它每次离开的代码开始for使用发电机。

现在,硬的部分:

第一次for调用从您函数创建的生成器对象,它将运行您函数中的代码,从开始一直运行到点击yield,然后它返回循环的第一个值。然后,每次随后的呼叫将运行您在函数中写入的循环的再次迭代,然后返回下一个值。这将一直持续到发电机被视为空,当函数运行时没有打中yield。这可能是因为循环已经结束,或者因为你不再满足"if/else".


您的代码解释

发电机:

# Here you create the method of the node object that will return the generator
def _get_child_candidates(self, distance, min_dist, max_dist):

    # Here is the code that will be called each time you use the generator object:

    # If there is still a child of the node object on its left
    # AND if the distance is ok, return the next child
    if self._leftchild and distance - max_dist < self._median:
        yield self._leftchild

    # If there is still a child of the node object on its right
    # AND if the distance is ok, return the next child
    if self._rightchild and distance + max_dist >= self._median:
        yield self._rightchild

    # If the function arrives here, the generator will be considered empty
    # there are no more than two values: the left and the right children

调用者 :

# Create an empty list and a list with the current object reference
result, candidates = list(), [self]

# Loop on candidates (they contain only one element at the beginning)
while candidates:

    # Get the last candidate and remove it from the list
    node = candidates.pop()

    # Get the distance between obj and the candidate
    distance = node._get_dist(obj)

    # If the distance is ok, then you can fill in the result
    if distance <= max_dist and distance >= min_dist:
        result.extend(node._values)

    # Add the children of the candidate to the candidate's list
    # so the loop will keep running until it has looked
    # at all the children of the children of the children, etc. of the candidate
    candidates.extend(node._get_child_candidates(distance, min_dist, max_dist))

return result

本代码包含几个智能部分 :

  • 循环在列表中反复出现, 但列表会扩展, 而循环正在迭代中 。 这是一个简洁的方法 来查看所有这些嵌套的数据, 即使它有点危险, 因为您可以以无限循环结束 。 在这种情况下,candidates.extend(node._get_child_candidates(distance, min_dist, max_dist))耗尽发电机的所有值,但while保持创建新生成的生成对象, 从而产生与前一个生成对象不同的值, 因为它不应用在同一节点上 。

  • 缩略extend()方法是一种列表对象方法,该方法预计可循环并增加其值到列表中。

通常,我们向它传递一份清单:

>>> a = [1, 2]
>>> b = [3, 4]
>>> a.extend(b)
>>> print(a)
[1, 2, 3, 4]

但在你的代码中,它有一个发电机, 这是很好的,因为:

  1. 您不需要两次阅读数值 。
  2. 你可能有很多孩子 你不想把他们都保存在记忆中

之所以有效,是因为 Python 并不在意一种方法的论据是否是一个列表。 Python 期望它能用字符串、列表、图普勒和生成器来操作。 这叫做鸭字打字, 也是Python之所以如此酷的原因之一。 但是这是另一个故事, 另一个问题...

您可以在这里停下来,或者读一下,看一个生成器的先进使用:

控制发电机耗竭

>>> class Bank(): # Let's create a bank, building ATMs
...    crisis = False
...    def create_atm(self):
...        while not self.crisis:
...            yield "$100"
>>> hsbc = Bank() # When everything's ok the ATM gives you as much as you want
>>> corner_street_atm = hsbc.create_atm()
>>> print(corner_street_atm.next())
$100
>>> print(corner_street_atm.next())
$100
>>> print([corner_street_atm.next() for cash in range(5)])
['$100', '$100', '$100', '$100', '$100']
>>> hsbc.crisis = True # Crisis is coming, no more money!
>>> print(corner_street_atm.next())
<type 'exceptions.StopIteration'>
>>> wall_street_atm = hsbc.create_atm() # It's even true for new ATMs
>>> print(wall_street_atm.next())
<type 'exceptions.StopIteration'>
>>> hsbc.crisis = False # The trouble is, even post-crisis the ATM remains empty
>>> print(corner_street_atm.next())
<type 'exceptions.StopIteration'>
>>> brand_new_atm = hsbc.create_atm() # Build a new one to get back in business
>>> for cash in brand_new_atm:
...    print cash
$100
$100
$100
$100
$100
$100
$100
$100
$100
...

注:Python 3, 用于 Python 3, 使用print(corner_street_atm.__next__())print(next(corner_street_atm))

它可以对控制获取资源等各种事情有用。

义大便,你最好的朋友

Itertools 模块包含操作可替换文件的特殊功能 。 是否想要重复生成器? 连锁二生成器? 组值与单线串连接的嵌入列表中?Map / Zip不创建其它列表吗 ?

然后,就刚刚import itertools.

举个例子,让我们看看四匹马赛的到货订单

>>> horses = [1, 2, 3, 4]
>>> races = itertools.permutations(horses)
>>> print(races)
<itertools.permutations object at 0xb754f1dc>
>>> print(list(itertools.permutations(horses)))
[(1, 2, 3, 4),
 (1, 2, 4, 3),
 (1, 3, 2, 4),
 (1, 3, 4, 2),
 (1, 4, 2, 3),
 (1, 4, 3, 2),
 (2, 1, 3, 4),
 (2, 1, 4, 3),
 (2, 3, 1, 4),
 (2, 3, 4, 1),
 (2, 4, 1, 3),
 (2, 4, 3, 1),
 (3, 1, 2, 4),
 (3, 1, 4, 2),
 (3, 2, 1, 4),
 (3, 2, 4, 1),
 (3, 4, 1, 2),
 (3, 4, 2, 1),
 (4, 1, 2, 3),
 (4, 1, 3, 2),
 (4, 2, 1, 3),
 (4, 2, 3, 1),
 (4, 3, 1, 2),
 (4, 3, 2, 1)]

了解迭代的内部机制

迭迭代是一个过程,意味着可迭代(实施__iter__()和迭代器(执行__next__()循环是您可以从中获取迭代器的任何对象。迭代器是允许您在迭代器上迭代的对象。

这篇文章中更多关于如何如何for环环工作.

又一个TRL;DR

列表中的迭代器: next()返回列表的下一个元素

热机发电机: next()将计算苍蝇上的下一个元素( 执行代码)

您可以看到生成/生成器作为手动运行控制流量从外部( 如继续循环一步骤) 调用next无论流量如何复杂。

Note发电机是不无一个普通函数。它会像本地变量( stack) 一样记得以前的状态( stack) 。请参看其他答案或文章以详细解释。生成器只能是曾经变热过一次. 你可以没有yield,但它不会是那么好, 所以它可以被认为是“非常好”的语言糖。

下面是浅白语言的例子。我将提供高层次人类概念与低层次Python概念之间的对应关系。

我想用数字序列操作, 但我不想用这个序列的创建来烦恼我自己, 我只想专注于我想做的操作。 因此, 我做以下工作:

  • 我打电话给你,告诉你,我想要一个数字序列 以特定的方式计算, 我让你知道算法是什么。
    此步骤对应于def内插入发电机函数,即包含yield.
  • 稍后,我告诉你, "好了,准备好告诉我数字的顺序"。
    此步骤对应于调用发电机函数, 以返回发电机对象 。注意不要告诉我任何数字 你只要拿起你的纸和铅笔
  • 我问你,"告诉我下一个号码",然后你告诉我第一个号码, 在那之后,你等我问你下一个号码。你的工作是记住你在哪里,你已经说过什么号码,下一个号码是什么。 我不在乎细节。
    此步骤对应于调用next(generator)在发电机的物体上。
    (在Python 2,.next是产生器物体的一种方法;在Python 3中,它被命名为.__next__,但正确的称呼方式是使用内置next()函数类似len().__len__)
  • ...重复前一步,直到...
  • 最终,你可能会走到尽头。你不会告诉我一个数字;你只会喊叫,“抓住你的马!我受够了!不再有数字了!”
    此步骤对应于生成器对象结束工作, 并提升StopIteration例外。
    生成器函数不需要提出例外。 当函数结束或发布时自动生成 。return.

这就是发电机(包含yield;它开始执行第一个next()时暂停yield,当要求next()它从最后一点继续值 。 它的设计完全符合 Python 的迭代协议, 它描述了如何按顺序请求值 。

循环程序最著名的用户是for在 Python 中命令。 所以, 当您做 :

for item in sequence:

这不重要,如果sequence是列表、字符串、字典或生成器对象对象如上文所述;结果相同:您逐个阅读顺序中的项目。

请注意def函数内含有yield关键字不是创建生成器的唯一方法; 它只是创建生成器的最简单的方法 。

将 " 更准确的信息 " 改为 " 更准确的信息 "迭代器类型、、 和收益单报表发电机发电机在 Python 文档中。

在描述如何使用发电机的许多伟大答案中, 我感到还没有给出一种答案。 这是编程语言理论的答案:

缩略yieldPython 语句中的 Python 语句返回一个发电机。 Python 中的发电机是一个函数返回续续(具体地说,是一种共同的例行公事,但延续是了解情况的一般机制)。

编程语言理论的继续是更根本的计算方法,但通常不会被使用,因为它们极难解释,也很难执行。但是,关于继续的理念很简单:是计算状态尚未完成。在这种状态下,变量的当前值、尚未执行的操作等等被保存。然后,在程序稍后的某个时候,可以援引继续,使程序的变量被重新设置到状态,保存的操作被执行。

以这种更一般性的形式出现的延续可以采取两种方式实施。call/cc方式,程序堆放的堆放实际上被保存, 当继续被引用时, 堆放的堆放就会被恢复 。

在继续传承风格(CPS)中,续编只是程序员明确管理和传到子例程的正常功能(仅在功能为头等语言的语文中),程序员明确管理和传到子例程。在这种风格中,程序状态代表关闭(和恰好在其中编码的变量),而不是堆叠中某处的变量。 管理控制流程的功能接受继续作为参数(在CPS的某些变异中,功能可能接受多重延续),并通过仅拨打这些函数来操纵控制流程,然后返回。一个非常简单的延续传承风格实例如下:

def save_file(filename):
  def write_file_continuation():
    write_stuff_to_file(filename)

  check_if_file_exists_and_user_wants_to_overwrite(write_file_continuation)

在此(非常简单化的)示例中,程序员将实际写入文件的操作保存为续存(这有可能是一个非常复杂的操作,有许多细节要写出来),然后将这一续存(即作为头等关闭)传递给另一个操作员,该操作员会做一些更多的处理,然后在必要时调用它。 (在实际的 GUI 编程中,我大量使用这种设计模式,要么是因为它可以节省我的代码线,要么更重要的是,在图形用户界面事件触发后管理控制流程。 )

这个职位的其余部分将不失为一般性,将连续性概念化为CPS, 因为它很容易理解和阅读。


现在让我们来谈谈Python的发电机。发电机是一个特定的子类型 继续。而一般而言,继续保留能够拯救a计算计算(即程序调用堆叠)发电机只能保存电离层的迭代状态。振动器虽然这一定义对发电机的某些使用情况略有误导性,例如:

def f():
  while True:
    yield 4

这显然是一个合理的可循环性, 其行为是明确定义的, 每当发电机转动时, 它就会返回 4 个( 并且永远这样做 ) 。 但是,在思考迭代器时, 可能不会想到这种典型的可循环性( 即, , ) 。for x in collection: do_something(x)这个例子说明了发电机的功率:如果有什么是迭代器,发电机可以挽救其迭代状态。

需要重申: 继续可以保存程序堆叠的状态, 发电机可以保存循环状态。 这意味着, 继续的威力比发电机大得多, 并且发电机也容易得多, 也容易得多。 语言设计师更容易执行, 程序设计员更容易使用( 如果您有时间燃烧, 试着阅读和理解)此页面的续续和调用/ cc).

但您可以很容易地实施(和概念化)发电机,作为延续传承风格的一个简单而具体的例子:

时 时 时yield被调用,它告诉函数返回一个延续。当再次调用函数时,它从它离开的开始。因此,在假假假代码(即不是伪代码,但不包括代码)中,生成器的next方法基本上如下:

class Generator():
  def __init__(self,iterable,generatorfun):
    self.next_continuation = lambda:generatorfun(iterable)

  def next(self):
    value, next_continuation = self.next_continuation()
    self.next_continuation = next_continuation
    return value

位于yield关键字实际上是实际生成功能的合成糖, 基本上类似 :

def generatorfun(iterable):
  if len(iterable) == 0:
    raise StopIteration
  else:
    return (iterable[0], lambda:generatorfun(iterable[1:]))

记住这只是假代号,而Python发电机的实际安装则更为复杂。 但是,作为了解正在发生的情况的一种练习,试图在不使用发电机物体的情况下,使用持续的传承风格来实施发电机物体。yield关键字。

什么是yieldPython的关键字是用吗?

答复大纲/摘要

  • 函数函数函数函数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)

首先,我们必须排队 发电机与内建功能,nextnext__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 fromPython 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 fromPEP380号

其他方法:关闭和投掷

缩略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

结论 结论 结论 结论 结论

我认为,我已处理了下列问题的所有方面:

什么是yieldPython的关键字是用吗?

事实证明yield我肯定我可以为此再增加更详尽的例子。如果你们想要更多或有建设性的批评,请在下面评论,让我知道。


附录:

顶级/接受的答复的优先程度**

  • 它被混淆了 是什么制造了易 易 易 性,仅以列表作为示例。见以上我的引用,但摘要:a易 易 易 性具有 a 的__iter__返回方法返回振动器。 A. A.振动器额外提供a.__next__方法,该方法隐含地称为:for循环直到它升起StopIteration,一旦它升起StopIteration它将继续这样做。
  • 然后,它用发电机表达式来描述发电机是什么。 因为发电机表达式只是创建一个振动器,它只是混淆了事情, 而我们仍然还没有达到yield部分。
  • 控制发电机耗竭他呼唤.next方法(仅在Python 2 中有效),当他应该使用内设函数时,next调用next(obj)这是一种适当的间接分解层,因为他的代码在Python 3号行不通。
  • 这跟什么无关yield完全没有。
  • 不讨论采用哪些方法yield与新功能一起提供yield fromPython 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,但你不能返回一个值。

脚注脚注

  1. 在向Python引入发电机概念的提案中,提到了CLU、Sather和“图标”等语言。 通常的想法是,功能可以维持内部状态,并产生用户需要的中间数据点。 这保证了这一功能能够维持内部状态,并产生中间数据点。业绩优于其他方法,包括Python线在某些系统上甚至都找不到

  2. 这意味着,例如,range对象不是物体Iteratori 尽管它们是可循环的, 因为它们可以被再利用。就像列表一样,它们__iter__方法返回迭代对象。

  3. yield最初作为声明被引入,意思是它只能出现在代码块的线条开头。yield创建收益表达式 。https://docs.python.org/2/reference/simple_stmts.html#grammar-token-yield_stmt这一变化是:拟议拟议拟议数允许用户像收到数据一样将数据发送到生成器中。 要发送数据, 就必须能够将数据指定给某些东西, 因此, 声明是行不通的 。