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

当前回答

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计算 fibonacci 序列的基础方法,解释如下:

def fib(limit=50):
    a, b = 0, 1
    for i in range(limit):
       yield b
       a, b = b, a+b

当你把这个输入你的REPL,然后尝试把它称为, 你会得到一个神秘的结果:

>>> fib()
<generator object fib at 0x7fa38394e3b8>

这是因为:yield发送到 Python 的信号, 您想要创建发电机发电机,即,一个根据需求产生价值的物体。

那么,您如何生成这些值? 可以通过使用内置函数直接实现next,或间接地,通过将其喂养到消耗价值的建筑上。

使用内置next()函数,直接引用.next/__next__迫使发电机产生一个价值:

>>> g = fib()
>>> next(g)
1
>>> next(g)
1
>>> next(g)
2
>>> next(g)
3
>>> next(g)
5

间接提供fib至 afor环环, alist初始初始化器, atuple初始化器, 或其他任何期望生成/ 产生值的对象, 您会“ 组装” 生成器, 直到它无法生成更多值( 并返回 ) :

results = []
for i in fib(30):       # consumes fib
    results.append(i) 
# can also be accomplished with
results = list(fib(30)) # consumes fib

同样,tuple初始化器 :

>>> tuple(fib(5))       # consumes fib
(1, 1, 2, 3, 5)

生成器与功能不同, 因为它很懒。 它通过保持本地状态, 并允许您在需要的时候恢复运行来达到这个目的 。

当你们第一次祈祷的时候,fib称其为:

f = fib()

Python 编译函数,遇到yieldkeyword and simply return a generate objects back at you. 似乎没有什么帮助。

当您要求它生成第一个值时,它直接或间接地执行它发现的所有语句,直到它遇到一个yield,然后,它产生回 价值,你提供yield并暂停。 举例来证明这一点, 让我们使用一些print电话(取代电话)print "text"如果Python 2 上写着:

def yielder(value):
    """ This is an infinite generator. Only use next on it """ 
    while 1:
        print("I'm going to generate the value for you")
        print("Then I'll pause for a while")
        yield value
        print("Let's go through it again.")

现在,输入REPL:

>>> gen = yielder("Hello, yield!")

您现在有一个生成对象, 正在等待命令来生成值。 使用next并查看打印的内容 :

>>> next(gen) # runs until it finds a yield
I'm going to generate the value for you
Then I'll pause for a while
'Hello, yield!'

未引用的结果是打印的内容。引用的结果是返回的内容yield调来next现在再次:

>>> next(gen) # continues from yield and runs again
Let's go through it again.
I'm going to generate the value for you
Then I'll pause for a while
'Hello, yield!'

发电机记得它被停停在yield value从那里打印下一条消息并搜索yield暂停该语句时(由于while(循环))

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

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

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

缩略yieldPython 中的关键字用于退出代码而不干扰本地变量状态,当函数再次被称为“执行”时,从我们离开代码的最后一点开始。

以下示例说明yield:

def counter():
    x=2
    while x < 5:
        yield x
        x += 1
        
print("Initial value of x: ", counter()) 

for y in counter():
    print(y)

上述代码产生以下输出:

Initial value of x:  <generator object counter at 0x7f0263020ac0>
2
3
4

佩顿有什么差错?

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

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

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

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

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

资料来源:https://www.simplilearn.com/tutorials/python-tutorial/yield-in-python

想象一下, 你创造了一个非凡的机器, 能够每天生成成千上万个灯泡。 机器用一个独特的序列号的盒子生成这些灯泡。 您没有足够的空间同时存储所有这些灯泡, 所以您想要调整它来生成点燃灯泡 。

Python 生成器与这个概念没有什么不同。 想象一下, 您有一个函数叫做 Python 。barcode_generator以生成框中独有的序列号。 显然,您可以通过函数返回大量这样的条形码,但受硬件(RAM)的限制。 更明智和空间效率更高的选项是按需生成这些序列号。

机器代码 :

def barcode_generator():
    serial_number = 10000  # Initial barcode
    while True:
        yield serial_number
        serial_number += 1


barcode = barcode_generator()
while True:
    number_of_lightbulbs_to_generate = int(input("How many lightbulbs to generate? "))
    barcodes = [next(barcode) for _ in range(number_of_lightbulbs_to_generate)]
    print(barcodes)

    # function_to_create_the_next_batch_of_lightbulbs(barcodes)

    produce_more = input("Produce more? [Y/n]: ")
    if produce_more == "n":
        break

注注:next(barcode)位数。

如你所可以看到,我们有一个自成一体的“功能” 每次生成下一个独特的序列号。此函数返回发电机发电机正如你可以看到的,我们不是每次需要新序列号时都调用这个功能,而是在使用新序列号。next()给发电机提供下一个序列号。

低拉隔热器

更确切地说,这个发电机是懒惰的滚动器迭代器是一个能帮助我们穿越物体序列的物体。 它被称为懒惰因为它在需要之前不会在内存中装入序列的全部项目。next在上一个示例中,直 直 直从迭代器获取下一个项目。内含循环方式正在使用 :

for barcode in barcode_generator():
    print(barcode)

这将无穷尽地打印条形码, 但你不会失去内存 。

换句话说,发电机看起来像a 函数但行为举止如迭代器。

现实世界应用?

最后, 真实世界应用程序 。 当您在大序列中工作时, 它们通常有用 。 想象一下读取巨大从含有数十亿记录的磁盘文件中取出文件。 在您能够处理其内容之前, 在内存中读取整个文件, 可能会不可行( 也就是说, 您会用完内存 ) 。