Python 中产出关键字的用法是什么? 它能做什么?

例如,我试图理解这个代码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_camedates 被调用时会怎样? 列表是否返回? 单一个元素吗? 是否再次调用? 以后的电话何时停止?


1. 本代码由Jochen Schulz(jrschulz)编写,他为公制空间制作了一个伟大的Python图书馆,与完整的源:模块mspace链接。


当前回答

在 Python 生成器( 一种特殊的迭代器) 中, 生成一系列的值, 产出关键字与 发电机功能的返回关键字相似 。

另一个令人着迷的是 生成关键词的方法 是保存生成功能的状态。

因此,我们可以设定一个数字 以不同的数值 每一次发电机产生时。

以下是一个例子:

def getPrimes(number):
    while True:
        if isPrime(number):
            number = yield number     # a miracle occurs here
        number += 1

def printSuccessivePrimes(iterations, base=10):
    primeGenerator = getPrimes(base)
    primeGenerator.send(None)
    for power in range(iterations):
        print(primeGenerator.send(base ** power))

其他回答

放弃是一个对象

函数的返回将返回单一值。

如果您想要一个函数返回一大组值,请使用收益率。

更重要的是,产量是障碍。

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

也就是说,它将从开始运行您函数中的代码,直到它产生效果。然后,它将返回循环的第一个值。

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

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

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);

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

佩顿有什么差错?

Python 中的 Yield 关键字类似于用于返回 Python 中的值或对象的返回语句。 但是, 存在微小的差别。 收益语句返回一个生成符, 而不是简单地返回一个值, 而返回一个函数的生成符。

在程序内,当您调用一个函数,该函数有一个输出语句时,一旦遇到一个输出,函数的执行即停止,然后将生成器的一个对象返回到函数调用器。用更简单的文字,产出关键字将把一个与该关键字一起指定的表达式转换为生成器对象,然后返回到调用器。因此,如果您想要获得在生成器对象内存储的值,则需要将该关键字复制到该对象上。

它不会破坏本地变量的状态。 当调用函数时, 执行将从最后一个输出表达式开始。 请注意, 包含输出关键字的函数被称为生成函数 。

当您使用含有返回值的函数时,每次调用函数时,该函数从一组新的变量开始。反之,如果使用一个生成函数而不是正常函数,则执行将从它左最后的位置开始。

如果您想要从函数中返回多个值, 您可以使用输出关键字来使用生成函数。 输出表达式返回多个值。 它们返回一个值, 然后等待, 保存本地状态, 然后再恢复 。

资料来源:https://www.simplilearn.com/tutorics/python-tutoric/yield-in-python。

要理解它的产值函数,人们必须理解发电机是什么。此外,在理解发电机之前,你必须理解易用的东西。易用 : 易用 : 要创建列表, 您自然需要能够逐个读取每个元素。 逐项读取其项目的过程被称为迭代 :

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

My list 是可替换的。 当您使用列表理解值时, 您会创建一个列表, 因此该列表是可替换的 :

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

所有可用于... 的数据结构都是可循环的; 列表、 字符串、 文件...

这些惯用方法很方便,因为您可以随意阅读,但您可以将所有值存储在记忆中,当您有许多值时,这些值并不总是可取的。 生成器: 生成器 A 也是一种迭代器, 一种特殊的迭代器, 只能迭代一次。 生成器不会将所有值存储在记忆中, 而是在苍蝇上生成值 :

发电机:发电机、发电机、发电机发电,但不储存能源;)

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

只要使用 () 而不是 [] , 列表理解就会变成发电机理解。 但是, 由于发电机只能使用一次, 您无法在我的生成器中执行 i 第二次 : 生成器计算 0, 然后丢弃它, 然后计算 1, 最后一次计算 4 。 典型的黑色盲人打破玉米 。

产出关键字的使用方式与返回相同,但函数返回生成器。

>>> def createGenerator():
...    mylist = range(3)
...    for i in mylist:
...        yield i*i
...
>>> mygenerator = createGenerator() 
>>> print(mygenerator) 
<generator object createGenerator at 0xb7555c34>
>>> for i in mygenerator:
...     print(i)
0
1
4 

这个例子本身是毫无用处的,但是当您需要函数返回大量数值,而只需要读一次,使用产量就方便了。

要掌握收益率,需要清楚的是,当函数被调用时,函数正文中写入的代码将不会运行。函数只返回生成对象。启动者可能会对此感到困惑。

第二,明白代码会从每次使用发电机时留下的代码中继续使用。

现在最困难的部分是:

第一次调用您函数所创建的生成器对象时, 它会运行函数中的代码, 从开始一直运行到产生, 然后返回循环的第一个值。 然后, 以后的每次调用都会运行您在函数中写入的循环的下一个迭代, 并返回下一个值。 这将一直持续到生成器被视为空, 当函数运行时没有被击中时该生成。 这可能是因为循环已经结束, 或者因为您不再满足于“ if/ else ” 。

个人理解 我希望帮助你!

总之,产出语句将您的函数转换成一个工厂,该工厂生产一个特殊对象,称为发电机,围绕您原始函数的正文包绕。当生成器被迭代时,它将执行您的函数,直到达到下一个输出时,然后中止执行,然后对传递到的数值进行评估。它重复了每次迭代的这一过程,直到执行路径退出函数。例如,

def simple_generator():
    yield 'one'
    yield 'two'
    yield 'three'

for i in simple_generator():
    print i

简单产出

one
two
three

电源来自使用循环计算序列的生成器, 生成器执行循环每次停止到“ ield ” 的下一个计算结果, 这样它就可以计算飞行上的列表, 好处是存储到特别大的计算中的内存

说你想创建一个自己的范围函数, 产生一个可循环的数字范围, 你可以这样做,

def myRangeNaive(i):
    n = 0
    range = []
    while n < i:
        range.append(n)
        n = n + 1
    return range

并像这样使用它;

for i in myRangeNaive(10):
    print i

但这效率低,因为

您创建了一个只使用一次的数组( 此废物内存) 。 此代码实际上会两次循环到该数组上 ! : () : ()

幸好吉多和他的团队 慷慨地开发了发电机 这样我们就可以这么做了

def myRangeSmart(i):
    n = 0
    while n < i:
       yield n
       n = n + 1
    return

for i in myRangeSmart(10):
    print i

在每次迭代中, 调用下一个发电机的函数执行该函数, 直至它到达“ ield” 语句停止和“ ields” 值, 或到达函数的终点。 在第一次调用的情况下, 下一个( ) 执行到产出语句, 并产生“ n ” , 下次调用它将执行递增语句, 跳回“ 此时” , 评估它, 如果是, 它会停止并再次产生“ n ” , 它会一直持续到状态返回错误, 发电机跳到函数结束的时候 。