导读:斐波那契的代码实现思路,更多思路请看其他文章。顺面讲解了普通函数加上field变成生成器。
一、理解斐波那契数列
斐波那契数列的由来,背景介绍:
有个数学家列昂纳多·斐波那契,他突发奇想,想了个问题。
假设有一对兔子,长两个月它们就算长大成年了。然后以后每个月都会生出1对兔子,生下来的兔子也都是长两个月就算成年,然后每个月也都会生出1对兔子了。这里假设兔子不会死,每次都是只生1对兔子。
第一个月,只有1对小兔子;
第二个月,小兔子还没长成年,还是只有1对兔子;
第三个月,兔子长成年了,同时生了1对小兔子,因此有两对兔子;
第四个月,成年兔子又生了1对兔子,加上自己及上月生的小兔子,共有3对兔子;
第五个月,成年兔子又生了1对兔子,第三月生的小兔子现在已经长成年了且生了1对小子,加上本身两只成年兔子及上月生的小兔子,共5对兔子;
这样过了一年之后,会有多少对兔子了呢?
这个就是兔子数列,也就是斐波那契数列。
它的规律是:1、1、2、3、5、8、13、21、34、55、89、144、233
它是怎么算出来的呢。。
由图可以看到,看出规律了吗?? 把两个值相加的结果作为下一次的基础再加前一个的值。图片的箭头,表示替换了位置。
由此,我们的思路有了,设置2个变量,让两个变量相加,再替换。
现在我们思路已经有了对吧! 接下来,是不是只要把这个思路放到循环里面,最后生成就完了。
#从0,1开始计算
def foo():
a,b = 0,1
mylist=[]
for x in range(10):
mylist.append(b)
a,b =b,a+b
print(mylist)
foo()
如果你想直接从1,1开始计算,则是先取a的值。一般我喜欢从0,1开始计算,看个人喜欢啦哈哈
#直接从1,1开始计算也行
def foo():
a,b = 1,1
mylist=[]
for x in range(10):
mylist.append(a)
a,b =b,a+b
print(mylist)
foo()
运行结果:
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
二、用生成器 解题斐波那契
导读:刚生成的列表,如果数据多的话,则很占空间。如果将来要生成十万以上,会boom掉。。有没有方法优化呢
把普通函数变成生成器,用关键字yield
def foo():
a,b = 0,1
for x in range(10):
yield b
a,b =b,a+b
f=foo()
print(f)
print(next(f))
print(next(f))
print(next(f))
运行结果:
<generator object foo at 0x0000000001199570>
1
1
2
解释:generator object 为生成器对象。yield 关键字做了2件事情,1,返回了一个结果,2,返回结果后暂停
yield 如果不理解,可以测试下就知道了
第一步测试:
def foo():
a,b = 0,1
print("----调试1----")
for x in range(10):
print("----调试2----")
yield b
print("----调试3----")
a,b =b,a+b
print("----调试4----")
foo()
运行结果:空的,也就是函数没有执行
第二步测试:
def foo():
a,b = 0,1
print("----调试1----")
for x in range(10):
print("----调试2----")
yield b
print("----调试3----")
a,b =b,a+b
print("----调试4----")
print(foo())
运行结果:
<generator object foo at 0x0000000000709620>
第三步测试:
def foo():
a,b = 0,1
print("----调试1----")
for x in range(10):
print("----调试2----")
yield b
print("----调试3----")
a,b =b,a+b
print("----调试4----")
f=foo()
print(next(f))
print("————————分割线————————")
print(next(f))
print("————————分割线————————")
print(next(f))
运行结果:
—-调试1—-
—-调试2—-
1
————————分割线————————
—-调试3—-
—-调试4—-
—-调试2—-
1
————————分割线————————
—-调试3—-
—-调试4—-
—-调试2—-
2
总结:
普通函数加了关键字yield后,就变成生成器了
yield b 这句话做了2件事情,1,返回了一个结果,2,返回结果后暂停