18

可能重复:
Python yield 关键字解释

有人可以在这里向我解释一下 yield 语句在这段代码中的实际作用:

 def fibonacci():
     a, b = 0, 1
     while True:
         yield a
         a, b = b, a+b

for number in fibonacci(): # 使用生成器作为迭代器;打印号码

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

下一个问题,对于 number in fibonacci(),这意味着函数中的每个数字还是什么?我同样对产量和“数量”实际上在做什么感到困惑。显然,我知道这意味着fibonacci()打印数字中的每个数字。我实际上是在不知道数字的情况下定义数字吗?

谢谢,如果我不清楚,对不起。顺便说一句,它适用于 Euler 项目,如果我知道如何很好地编程,这将是一件轻而易举的事,但我正在努力学习这一点。

4

4 回答 4

11

Usingyield使函数成为生成器。生成器将在每个循环中继续产生a变量,等待直到next()调用生成器的方法以继续进行下一次循环迭代。

或者,直到你return或被StopIteration提出。

稍作修改以显示使用StopIteration

>>> 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
>>>
于 2012-08-22T08:11:25.190 回答
4

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

请注意,函数内部的对象在调用next. 这意味着,当代码在下一个循环中继续执行时,yield被调用的范围内的所有对象的值都来自上一次next调用返回的点。

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

于 2012-08-22T08:11:13.520 回答
4

生成器具有可迭代的特殊属性,它不会为它们的值消耗内存。

他们通过计算新值来做到这一点,在迭代时需要它。

IE

def f():
    a = 2
    yield a
    a += 1

for ele in f():
    print ele

会打印

 2

因此,您将函数用作不断返回值的可迭代对象。当您需要大量内存使用时,这尤其有用,因此您无法负担使用列表推导式

IE

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

将 10 个内存空间用于 int 作为列表

但如果你只是想迭代它,不要单独访问它

改为使用会非常节省内存

def f():
    i=0
    while i<10
        yield i*10
        i += 1

这将使用 1 个内存空间,因为我不断被重用

一个捷径是

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

您可以执行以下任何操作

for ele in f():

for ele in li:

for ele in ge:

获得等效结果

于 2012-08-22T08:20:33.817 回答
1

这个答案是对yield语句以及迭代器和生成器的一个很好的解释。

具体在这里,第一次调用fibonaci()会初始化a为0,初始化b为1,进入while循环并返回a。任何下一次调用都将在yield语句之后开始,影响bto aa+bto b,然后转到语句的下一次迭代while,再次到达该yield语句,然后a再次返回。

于 2012-08-22T08:17:38.910 回答