关于python:函数中的”yield”语句是什么?

What is a “yield” statement in a function?

本问题已经有最佳答案,请猛点这里访问。

Possible Duplicate:
The Python yield keyword explained

有人能给我解释一下yield语句在这段代码中的实际作用吗?

1
2
3
4
5
 def fibonacci():
     a, b = 0, 1
     while True:
         yield a
         a, b = b, a+b

对于EDOCX1中的数字(0):使用生成器作为迭代器;打印数字

到目前为止我所理解的是,我们正在定义一个没有参数的函数finonacci()?在函数内部,我们将ab定义为0和1,接下来,虽然这是真的,但我们将生成a。这到底在做什么?此外,在生产a的同时?a现在等于b,而b现在等于a + b

下一个问题,对于EDOCX1中的数字(0),这是否意味着函数中的每个数字,或者什么?我同样无法理解收益率和"为数字"实际上在做什么。很明显,我知道这意味着fibonacci()打印号中的每个数字。我真的是在不知道的情况下定义数字吗?

谢谢,对不起,如果我不清楚。顺便说一句,这是为ProjectEuler准备的,如果我知道如何很好地编程,这将是一件轻而易举的事情,但我正在努力学习这一点。


使用yield使函数成为生成器。生成器将继续在每个循环上生成a变量,直到调用生成器的next()方法继续下一个循环迭代。

或者,直到你长大。

稍作修改以显示使用StopIteration

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
>>> def fib():
...     a = 0
...     b = 1
...     while True:
...         yield a
...         a = b
...         b += a
...         if a > 100:
...             raise StopIteration
...
>>>
>>> for value in fib():
...     print value
...
0
1
2
4
8
16
32
64
>>>

>>> # assign the resulting object to 'generator'
>>> generator = fib()
>>> generator.next()
0
>>> generator.next()
1
>>> for value in generator:
...     print value
...
2
4
8
16
32
64
>>>


生成器有一个特殊的特性,即不为其值消耗内存。

当迭代时需要新值时,它们通过计算新值来实现这一点。

1
2
3
4
5
6
7
def f():
    a = 2
    yield a
    a += 1

for ele in f():
    print ele

将打印

1
 2

因此,您使用的函数是一个可重复返回值的iterable。当您需要大量的内存使用时,这尤其有用,因此您负担不起使用列表理解。

1
li = [ele*10 for ele in range(10)]

以10个内存空间作为int列表

但是,如果您简单地想遍历它,就不要单独访问它。

相反,使用

1
2
3
4
5
def f():
    i=0
    while i<10
        yield i*10
        i += 1

当我不断被重用时,它将使用1个内存空间

这个的捷径是

1
ge = (i*10 for i in range(10))

您可以执行以下任一操作

1
2
3
4
5
for ele in f():

for ele in li:

for ele in ge:

获得等效结果


当代码调用fibonacci时,将创建一个特殊的生成器对象。请注意,没有执行任何代码-只返回生成器对象。当您稍后调用其next方法时,该函数将执行,直到遇到yield语句为止。返回提供给yield的对象。当您再次调用next方法时,函数再次执行,直到遇到yield为止。当没有更多的yield语句并且达到函数结束时,会引发StopIteration异常。

请注意,函数中的对象在调用next之间保留。这意味着,当代码在下一个循环上继续执行时,调用yield的范围内的所有对象的值都是从上一个next调用返回的点开始的。

关于生成器,最酷的是它们允许使用for循环进行方便的迭代。for循环从fibonacci调用的结果中获取一个生成器,然后使用generatior对象的next方法执行循环检索元素,直到遇到StopIteration异常。


这个答案很好地解释了yield语句,以及迭代器和生成器。

具体来说,第一次调用fibonaci()会初始化a为0,b为1,进入while循环并返回a。下一次调用将在yield语句后开始,影响baa+bb,然后转到while语句的下一个迭代,再次到达yield语句,并返回a