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

当前回答

收益率与返回相似。区别是:

收益率使函数可适用(在下个示例中)primes(n = 1)函数成为可使用性) 。
它的基本意思是 函数下次被调用时, 它将继续从它离开的地方( 位于yield expression).

def isprime(n):
    if n == 1:
        return False
    for x in range(2, n):
        if n % x == 0:
            return False
    else:
        return True

def primes(n = 1):
   while(True):
       if isprime(n): yield n
       n += 1 

for n in primes():
    if n > 100: break
    print(n)

在上述例子中,如果isprime(n)这是真的, 它会返回质号。 在下次迭代中, 它会从下一行继续

n += 1  

其他回答

yield简直就像return区别在于,下次你打电话给发电机时,从最后一次呼叫开始执行。yield与返回不同的语句,当生成时, 堆叠框架不会被清理, 但是控件会被转回调用方, 所以下次调用函数时, 它的状态将会恢复 。

对于您的代码,函数get_child_candidates动作就像一个循环器,这样当您扩展列表时,它会一次向新列表添加一个元素。

list.extend在你公布的代码样本中, 只需将图普还给列表, 并附加到列表中, 就会更加清晰 。

缩略yieldKeyword 简单收集返回结果。yield类似return +=

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

还有一个yield用途和含义(自 Python 3.3 以来):

yield from <expr>

发自PEP 380-从属子生成器的语法:

提议对发电机使用语法,将部分操作权下放给另一个发电机,这样可以将含有“当量”的代码部分计入到另一个发电机中。此外,允许次发电机返回一个值,并将价值提供给授权发电机。

新的语法也为当一个发电机再生一个发电机产生的另一个发电机价值时实现最佳化开辟了一些机会。

此外,这笔将引入(自Python 3. 5) :

async def new_coroutine(data):
   ...
   await blocking_action()

避免与常规发电机混淆(今天)yield两者都使用)。

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

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