有人可以向我解释一下yield语句在这段代码中实际做了什么:
def fibonacci():
a, b = 0, 1
while True:
yield a
a, b = b, a+b
表示fibonacci()
中的数字:#将生成器用作迭代器;打印号码
到目前为止我所理解的是,我们正在定义一个没有参数的函数finonacci()
?
我们定义a
和b
的函数内部等于0和1,接下来,虽然这是真的,但我们正在屈服a
。这到底是做什么的?而且,在屈服a
的同时? a
现在等于b
,而b
现在等于a + b
。
下一个问题,对于fibonacci()
中的数字,这对于函数中的每个数字还是什么意味着什么?我同样难以理解产量和“数量”实际上在做什么。显然我知道它对fibonacci()
打印数字中的每个数字都有意义。我是否真的在不知情的情况下定义数字?
谢谢,对不起,如果我不清楚的话。顺便说一句,这是项目欧拉,如果我知道如何编程这将是一件轻而易举的事情,但我正在努力学习这一点。
答案 0 :(得分:11)
使用yield
使该函数成为生成器。
生成器将继续在每个循环上产生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
>>>
答案 1 :(得分:4)
当代码调用fibonacci
时,会创建一个特殊的生成器对象。请注意,没有代码被执行 - 只返回一个生成器对象。当您稍后调用其next
方法时,该函数将执行,直到遇到yield
语句。提供给yield
的对象将被返回。当您再次调用next
方法时,该函数会再次执行,直到遇到yield
为止。如果没有yield
语句并且到达函数结尾,则会引发StopIteration
异常。
请注意,函数内的对象在next
的调用之间保留。这意味着,当代码在下一个循环中继续执行时,调用yield
的范围内的所有对象的值都会从之前的next
调用返回的位置开始。
关于生成器的一个很酷的事情是它们允许使用for
循环进行方便的迭代。
for循环从fibonacci
调用的结果中获取生成器,然后使用next
生成器对象的方法执行循环检索元素,直到遇到StopIteration
异常。
答案 2 :(得分:4)
生成器具有可迭代的特殊属性,它们不会为其值消耗内存。
他们通过计算新值来实现这一点,当迭代时需要它。
即。
def f():
a = 2
yield a
a += 1
for ele in f():
print ele
会打印
2
所以你使用一个函数作为一个可以保持返回值的迭代。 当您需要大量内存使用时,这尤其有用,因此您无法负担列表推导的使用
即
li = [ele*10 for ele in range(10)]
将整个内存空间作为列表
但如果您只想迭代它,则不能单独访问
使用
来提高内存效率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:
获得相同的结果
答案 3 :(得分:1)
这个answer是对yield
语句以及迭代器和生成器的一个很好的解释。
具体来说,第一次调用fibonaci()
会将a
初始化为0,将b
初始化为1,输入while循环并返回a
。
任何下一个电话会在yield
语句后开始,影响b
至a
,a+b
至b
,然后转至{{1}的下一次迭代1}}语句,再次访问while
语句,然后再次返回yield
。