小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
复盘python,发现生成器一个有趣的东西
首先看现象
用生成器实现一个斐波那契数列
def fibonacci(times):
n = 0
a, b = 0, 1
while n < times:
# print(b)
yield b
a, b = b, a + b
n += 1
return
if __name__ == "__main__":
g = fibonacci(5)
print(type(g)) # 类型为generator
print(type(fibonacci(5))) # 类型为generator
print(id(g))
# for i in g:
# print(i)
print(id(fibonacci(5))) # 两者的内存地址也一样
while True:
try:
x = next(g) # 循环输出生成器的值,此种调用可输出所有的值
print("value:%d" % x)
except StopIteration as e:
print("StopIteration")
break
执行上述代码,运行结果如下:
value:1
value:1
value:2
value:3
value:5
StopIteration
如果把上述代码中的x = next ( g ) 改为 x= next( fibonacci ( 5 ))
运行则会陷入死循环,只输出value:1
通过debug调试:
第一种方式执行到yield,第二次会接着执行yield后的代码
第二种方式每次都从函数开始执行到yield,yield后面不会执行
这是什么原因,两者都是生成器,内存地址也一样,按道理是一个生成器,运行结果为什么会不一样呢
运行结果不一样的原因
原因在于
(1)while 循环内
next(fib(5)) 你这个next() 函数调用一次,函数中的 f(5) 是新的生成器调用,每次都是不同的生成器对象。
(2) while 循环前
定义的 g=fibonacci(5) 然后在next(g)中的这个g是固定的一个生成器对象。**
id相同的原因
不过关于 id 相同的问题,Python 将内存划分为不同的区块,最小的单位为 block ,在生成对象时将会分配这个 block。在一个对象被销毁的时候,它的 block 被回收加入到 free-block 的顶端。如果紧接着新生成的对象和原对象大小一致的话,那么将直接从 free-block 取出我们刚刚放进去的 block。
因为 generator 对象不断销毁新建,每次新建时都使用上次 release 的 block