何为使用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将一个元素转换成一个生成器。一个生成器的行为就像一个函数,直到某东西“当”为“当”为止。发电机停止直到下一个调用,并且从与开始的完全相同的点继续。您可以通过调用所有“当”值的序列,从一个角度获得所有“当”值的序列。list(generator()).

其他回答

对于那些更喜欢最低限度工作实例的人来说,考虑一下这次交互式的Python会议:

>>> def f():
...   yield 1
...   yield 2
...   yield 3
... 
>>> g = f()
>>> for i in g:
...   print(i)
... 
1
2
3
>>> for i in g:
...   print(i)
... 
>>> # Note that this time nothing was printed

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

缩略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关键字。

虽然很多答案 表明你为什么会使用yield要创建生成器, 有更多的用途yield来传递两个代码区块之间的信息。我不会重复任何已经提供的关于使用yield创建生成器。

帮助理解什么是yield在以下代码中,您可以使用手指通过任何具有yield。 每次你的手指碰到yield你必须等待next或 a/send要输入。当next被调用,你通过代码追踪 直到你击中yield. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .yield被评价并返回到打电话者... 然后你等待。next被再次调用,您通过代码执行另一个循环。 但是,你会注意到,在一条共同的常规中,yield也可以与 a 一起使用send... 将会从调用器中发送一个值产生函数。如果send给给, 然后给yield接收发送的值,然后吐出左边的左手侧... 然后通过代码的追踪进展,直到你击中yield再次返回(在结尾处返回值,如同next也有人打电话))

例如:

>>> def coroutine():
...     i = -1
...     while True:
...         i += 1
...         val = (yield i)
...         print("Received %s" % val)
...
>>> sequence = coroutine()
>>> sequence.next()
0
>>> sequence.next()
Received None
1
>>> sequence.send('hello')
Received hello
2
>>> sequence.close()

就像每个答案都暗示的那样yield用于创建序列生成器。 它用于动态生成某些序列。 例如, 在网络上逐行读取文件行时, 您可以使用yield函数如下:

def getNextLines():
   while con.isOpen():
       yield con.read()

您可在您的代码中使用以下代码:

for line in getNextLines():
    doSomeThing(line)

执行控制控制

执行控制将从下拉林( GetNextLines) 转到for当输出被执行时循环。 因此, 每次引用 NextLines () 时, 执行从上次暂停的点开始 。

因此,简言之,一个函数具有以下代码

def simpleYield():
    yield "first time"
    yield "second time"
    yield "third time"
    yield "Now some useful value {}".format(12)

for i in simpleYield():
    print i

将打印

"first time"
"second time"
"third time"
"Now some useful value 12"

放弃是一个对象

A A Areturn在函数中返回单一值。

如果您愿意,如果需要函数返回一大批值,使用yield.

更重要的是yield是 a 是障碍屏障.

就像CUDA语言中的屏障, 它不会转移控制 直到它完成。

也就是说,它会运行您函数的代码 从开始直到启动yield。然后,它将返回循环的第一个值。

然后,其他每通电话都会运行您在函数中写下的循环, 返回下一个值, 直到没有任何值可以返回 。