何为使用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 空间.

当前回答

放弃是一个对象

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

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

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

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

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

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

其他回答

还有一件事情要提: 产量的函数其实不一定要终止。我写了这样的代码:

def fib():
    last, cur = 0, 1
    while True: 
        yield cur
        last, cur = cur, last + cur

这样我就可以用在别的代码里了

for f in fib():
    if some_condition: break
    coolfuncs(f);

它确实有助于简化一些问题,使一些事情更容易处理。

要理解的快捷键yield

当您看到一个函数yield语句,应用这个简单易懂的把戏来理解会发生什么:

  1. 插入一行result = []3⁄4 ̄ ̧漯B
  2. 替换各yield exprresult.append(expr).
  3. 插入一行return result函数的底部。
  4. - 耶 - 不再yield语句! 读取并找出代码 。
  5. 将函数与原始定义比较。

这个把戏也许能让你了解 函数背后的逻辑, 但实际发生什么了?yield与以列表为基础的方法发生的情况大不相同。 在许多情况下, 收益率方法会提高记忆效率和速度。 在其他情况下, 这个把戏会使你陷入无穷无尽的循环中, 即使最初的函数效果很好。 阅读更多来学习...

不要弄乱你的循环器 循环器和发电机

首先,动态自动交换协议- 当你写作时

for x in mylist:
    ...loop body...

Python 执行以下两个步骤:

  1. 获得一个循环器用于mylist:

    调调iter(mylist)->此返回一个带有next()方法(或)__next__()Python 3 中。

    [这是大多数人忘记告诉你的一步]

  2. 使用迭代器绕过项目 :

    继续叫next()从第1步返回的迭代器上的迭代器 方法上的迭代器 。next()指定用于x并执行环环体。如果有例外StopIteration从内部筹集next(),这意味着循环器中没有更多的值,循环就退出了。

真相是 Python 随时随地执行上述两步环绕环绕对象的内容 - 所以它可能是循环的, 但它也可以是代码otherlist.extend(mylist)(此处(此处)otherlist是 Python 列表)。

mylist易 易 易 性因为它执行了循环协议。在用户定义的类中,您可以执行__iter__()使类的示例可易易易操作的方法。 此方法应该返回振动器对象。next()两种方法都可实施。__iter__()next()在同一类同级同级同级同级同级同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同班同同同班同班同班同班同班同同班同班同班同班同班同班同同同班同班同班同班同班同同班同同同同同班同班同班同班同同班同班同班同班同同同同同同同班同班同班同同同同同同同班同同同同同同班同__iter__()返回返回self。这将对简单案例有效,但当您想要两个迭代器同时绕过同一个对象时,则不会有效。

这就是传动程序,许多物体执行这个程序:

  1. 内置列表、词典、图普尔、设置和文件。
  2. 执行的用户定义的分类__iter__().
  3. 发电机。

注 afor循环不知道它处理的是什么样的物体 - 它只是遵循循环程序, 并且很乐意按项目逐项获得它调用的项目next(). 内置清单逐项归还其物项,词典则逐项归还键键一个一个一个一个,文件返回线条一个一个一个一个一个,等等。 和发电机返回。 。 。yield输入 :

def f123():
    yield 1
    yield 2
    yield 3

for item in f123():
    print item

取代yield如果您有三种语句return以 国 国 国 国 国 国 国 国 国 国 国 国 国 国 国 国 国 国 国 国 国 国 国 国 国 国 国 国 国 国 国 国 国 国 国 国 国 国 国 国 国 国 国 国 国 国 国 国 国 国 国 国 国 国 国 国 国 国 国f123()只有第一个被执行, 而功能会退出。 但是,f123()没有普通函数为普通函数的普通函数为普通函数。f123()被召唤的,被召唤的,被召唤的,被召唤的,返回输出语句中的任何值。它返回生成对象。它返回一个生成对象。此外,函数并不真正退出 -它进入中止状态。当for循环试图环绕到发电机对象上, 函数从中止状态恢复 。yield执行下一行代码,在此情况下,ayield语句,然后返回该语句,作为下一个项目返回该语句。这种情况发生到函数退出时,然后生成器产生StopIteration,并循环出口。

因此,发电机对象有点像一个适配器—— 一方面,它展示了迭代程序,通过曝光__iter__()next()保存for循环快乐。 但是,在另一端, 它运行的函数足够从中获取下一个值, 并将其重新置于暂停模式 。

为什么使用发电机?

通常情况下, 您可以写入不使用发电机的代码, 但使用相同的逻辑逻辑。 一个选项是使用我之前提到的临时列表“ trick ” 。 这不会在所有情况下都有效, 例如, 如果您有无限循环, 或者当您有很长的列表时它可能无效地使用内存 。 另一种方法是执行一个新的可循环的类“ 某些东西 ” , 将国家保留在成员中, 并在成员中执行下一个逻辑步骤 。next()(或)__next__()Python 3 方法中的代码 。 取决于逻辑, 内部的代码 。next()方法最终可能会看起来非常复杂,容易出现虫子。 这里的发电机提供了清洁和容易的解决方案。

发电机可以使个别经过处理的物品立即得到处理(不必等待整个收集过程的处理),下面的例子说明了这一点。

import time

def get_gen():
    for i in range(10):
        yield i
        time.sleep(1)

def get_list():
    ret = []
    for i in range(10):
        ret.append(i)
        time.sleep(1)
    return ret


start_time = time.time()
print('get_gen iteration (individual results come immediately)')
for i in get_gen():
    print(f'result arrived after: {time.time() - start_time:.0f} seconds')
print()

start_time = time.time()
print('get_list iteration (results come all at once)') 
for i in get_list():
    print(f'result arrived after: {time.time() - start_time:.0f} seconds')

get_gen iteration (individual results come immediately)
result arrived after: 0 seconds
result arrived after: 1 seconds
result arrived after: 2 seconds
result arrived after: 3 seconds
result arrived after: 4 seconds
result arrived after: 5 seconds
result arrived after: 6 seconds
result arrived after: 7 seconds
result arrived after: 8 seconds
result arrived after: 9 seconds

get_list iteration (results come all at once)
result arrived after: 10 seconds
result arrived after: 10 seconds
result arrived after: 10 seconds
result arrived after: 10 seconds
result arrived after: 10 seconds
result arrived after: 10 seconds
result arrived after: 10 seconds
result arrived after: 10 seconds
result arrived after: 10 seconds
result arrived after: 10 seconds

TL; DR TR; TL; TDR

代替此:

def square_list(n):
    the_list = []                         # Replace
    for x in range(n):
        y = x * x
        the_list.append(y)                # these
    return the_list                       # lines

这样做:

def square_yield(n):
    for x in range(n):
        y = x * x
        yield y                           # with this one.

每当你发现自己从头到尾 编造了一张清单yield换成每块

这是我第一次"啊哈"节奏节奏


yield是 a 是糖糖

构建一系列材料

相同行为 :

>>> for square in square_list(4):
...     print(square)
...
0
1
4
9
>>> for square in square_yield(4):
...     print(square)
...
0
1
4
9

不同的行为 :

成绩是单行:只有一次循环才能通过。当一个函数在其中产生产量时,我们把它称为发电机功能和一个振动器也就是它所返回的。这些术语是明亮的。我们失去了一个容器的方便,但获得了一系列的能量, 而这些能量是按需要计算, 并且任意地长。

成绩是懒惰,它会推迟计算计算。当你叫它时,它不会实际执行。返回函数返回振动器对象记得它留下的痕迹 每次你打电话next()转动器上(这发生在换行)行刑的几英寸向下一产地前进。return提高停止电流并结束序列( 这是循环的自然端 ) 。

成绩是多功能性。数据不必全部储存在一起,数据可以一次提供一次。数据可以是无限的。

>>> def squares_all_of_them():
...     x = 0
...     while True:
...         yield x * x
...         x += 1
...
>>> squares = squares_all_of_them()
>>> for _ in range(4):
...     print(next(squares))
...
0
1
4
9

需要时多个通行证系列剧不会太长,只是打个电话list()以下列方式:

>>> list(square_yield(4))
[0, 1, 4, 9]

最聪明的词选yield原因原因双两个意思应用 :

收益率生产或供应(如农业)

...在系列中提供下一个数据

收益率- 放弃或放弃(与政治权力一样)

...在传动器推进之前,将CPU执行。

虽然很多答案 表明你为什么会使用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()