python斐波那契数列for循环_从零开始学习PYTHON3讲义
(六)for循环跟斐波那。。。
《从零开始PYTHON3》第六讲
⼏乎但凡接触过⼀点编程的⼈都知道for循环,在⼤多数语⾔的学习中,这也是第⼀个要学习的循环模式。
但是在Python中,我们把for循环放到了while循环的后⾯。原因是,Python中的for循环已经完全不是你知道的样⼦了。
for循环
以c语⾔为例,for循环⼏乎是同while循环完全相同的功能。在Python中,for循环经过全新的设计,实际只⽀持⼀个功能,当然也是编程最常⽤到的功能,就是“遍历”。
所谓遍历(Traversal),是指沿着某条确定的搜索路线,依次对序列中的每个结点(每个元素)均做⼀次且仅做⼀次访问。
⽐如最常见的字符串,实际就是⼀个序列。字符串“abcdefg”,中间包含7个字母,每个字母就是⼀个结点。“沿着某条确定的搜索路线”,其实指的就是按照何种规则来顺序访问字符串中的每个结点。最常见的可以使从开始到结尾,或者从结尾到开始。
我们先使⽤while循环来做⼀个字符串的遍历:s="abcdefg"
i = 0
while i < len(s):
print(s[i])
i += 1
在这个例⼦中,我们先定义了⼀个字符串,设定循环初始值0。while循环的边界条件使⽤了内置标准函数len(),这个函数的功能是给出参数中包含的元素个数,在这⾥是字符的个数。
随后在循环体中我们使⽤print函数在每次循环中打印出来⼀个结点(⼀个字符)。s[i]是s字符串中,第i个字符(结点)的意思,i在这⾥有⼀个专有名词叫做“下标”,你可以相像数学中常⽤的$ S_i $形式。这种访问某个序列中具体某个元素的⽅式是今天的重点之⼀。
这⾥i的取值范围是从0开始,因此最⼤可以到字符串中字符总数-1。最后的i += 1,指的是按照从串头到串尾的⽅式,循环访问整个字符串中的所有字符。程序的执⾏结果是这个样⼦:a
c语言斐波那契数列b
c
d
e
f
g补充⼀个⼩知识,刚才的循环中,我们使⽤了while i < len(s):,这可以⼯作的很好,理解起来也不难。但实际上,下⾯这样做效率更⾼:
n=len(s)
while i < n:
...
原因是,在前⼀个写法中,len这个函数会执⾏很多次,循环每⼀次都要重新执⾏。⽽在后⾯的写法中,len函数只需要执⾏⼀次。在其后的循环中,直接使⽤⼀个变量的值就要快多了。
遍历是编程中最常⽤到的操作,也是最简单的算法,希望你理解“遍历”的含义了。
接下来我们看⼀看for循环来实现上⾯同样的功能:for a in "abcdefg":
print(a)
仅有两⾏代码,完成跟上⾯while循环程序完全相同的功能,简洁了很多。执⾏结果跟上⾯完全⼀样,就不再重贴了。为了便于理解,我使⽤伪代码把for循环的基本形式重写⼀遍:for 遍历变量 in 序列型的数据:
循环体,每次循环执⾏⼀遍,每次“遍历变量”会有⼀个新值
这就是for循环的最基本形式。for/in/:是Python中的保留字。循环最终会执⾏的次数,等同于“序列型数据”中的元素个数。“遍历”是对所有元素都要循环访问⼀遍。
列表
for循环遍历的对象必须是⼀个序列类型。序列类型并不是在Python中有⼀种特定的类型,⽽是⼀种统称。可以理解为有顺序、能顺序访问的类型都叫序列类型。列表类型是序列类型的⼀种。字符串类型也是序列类型的⼀种。
先看看数字的列表。这是⼀个数字列表的样⼦:[2,3,8.3,34,55,23]
使⽤中括号圈起来的,⼀组⽤逗号隔开的元素,就是列表。列表是Python六⼤数据类型中的⼀种,我们现在已经学习过了3种基本数据类型,数字、字符串、列表。这⼀讲我们只是简单引⼊列表的概念,来帮助我们理解“遍历”,在第⼋讲中,我们将正式⽽且更深⼊的讲解列表这种数据类型。
跟字符串⼀样,对数字的列表同样可以使⽤len函数:>>> len([2,3,8.3,34,55,23])
6
我们同样可以使⽤for循环对数字列表进⾏遍历,⽐如:datas = [2,3,8.3,34,55,23];
for x in datas:
print(x)
#下⾯是执⾏的结果:
2
3
8.3
34
55
23
上⾯的数字列表中,我们混合了整数和浮点⼩数。从技术上讲,列表中还可以同时包含“布尔”和“字符串”类型的数据。只是因为不同的数据类型,难以有共同的处理⽅式,放到同⼀个列表中也没有办法得到程序效率上的优势,所以并不推荐那样使⽤。
只要是列表的形式,就可以使⽤for循环来进⾏遍历操作,从⽽提⾼处理速度。
我们再来对⽐遍历数字列表的while循环模式和for循环模式:#⾸先看while循环
i=0
while i<5:
print(i)
i += 1
#下⾯是for循环的⽅式
for i in [0,1,2,3,4]:
print(i)
#两种循环的执⾏结果都是⼀样的:
2
3
4
可以看到,for循环专门为了遍历操作⽽⽣,在处理序列数据的时候,程序简洁、代码少、效率⾼。⽽while循环则有更强的通⽤性,但在处理遍历任务的⽅⾯则略微⿇烦。
为了让for能够处理更多通⽤的任务,Python提供了⼀个内置的标准函数range来⾃动⽣成⼀个序列,使⽤⽅法的伪代码是:#单参数⽅式,⽣成由0开始,到⼩于最⼤值的整数序列
range(最⼤值)
#双参数⽅式,⽣成由最⼩值到最⼤值(不包含最⼤值本⾝)的整数序列
range(最⼩值,最⼤值)
#三参数模式,⽣成由最⼩值到最⼤值,以步长为递增的序列
range(最⼩值,最⼤值,步长)
我们来看⼀组实际使⽤的例⼦来加深印象:for i in range(5):
print(i)
#执⾏结果是:
1
2
3
4
for i in range(1,6):
print(i)
#执⾏结果是:
1
2
3
4
5
for i in range(1,10,2):
print(i)
1
3
5
range的注意事项是:range的参数、返回的序列都必须是整数。
我们前⾯见过了很多操作符,长得很不像关键字,⽐如+、-,今天我们终于看到了⼀个相反的例⼦,in操作符更像关键字,⽽不像操作符。当然操作符属于关键字的⼀种。
除了在for循环中使⽤in操作符,in还可以⽤于逻辑判断。⽐如:"北京" in "今天下⾬的地区有:北京、天津、河北" #结果是true
59 in range(60,101) #结果为:false
挑战
我们今天的挑战内容是编程⽣成斐波那契数列(Fibonacci sequence)。
斐波那契数列指的是这样⼀个数列: 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89...,这个数列从第3项开始,每⼀项都等于前两项之和。
今天学习的主要内容是for循环,所以当然这个挑战要使⽤for循环来完成,⽣成斐波那契数列的前100项。
⽼办法,请⼤家先认真思考,⽤流程图或者伪代码描述⾃⼰的思路,觉得思路清晰了,再看下⾯的内容。
我们继续使⽤快速原型法,⾸先是理清程序的需求,当做注释内容写⼊到程序:"""
使⽤for循环⽣成前100项斐波那契数列
作者:Andrew
斐波那契数列指的是这样⼀个数列 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89...
这个数列从第3项开始,每⼀项都等于前两项之和。
"""
接下来我们梳理在程序主体循环之前应当准备好的变量和初始值:#以序列中任意连续3个数字来看
#a代表其中第⼀个数字,初始是1
a = 1
#b代表其中第⼆个数字,初始是1
b = 1
#c代表第三个数字,应当是a+b的和,但当前尚未进⼊循环,所以赋值为0
#因为python语⾔使⽤变量前⽆需声明,所以实际上c=0可以省略
c = 0
#遍历所⽤变量在for循环中定义,这⾥忽略
跟上⼀讲的例⼦不同,斐波那契数列肯定是边⽣成边输出,所以肯定是要在循环之内来完成输出的⼯作。所以不像上⼀讲的例⼦,可以先确定输出的内容。
直接进⼊到考虑循环体的环节,⾸先依然是循环的边界:#从第3项开始,循环到第101项
for i in range(3,101):
循环到101项的意思是因为,前⾯讲过了,range函数所产⽣的序列,不包含给定的最⼤值本⾝,所以range(3,101)实际会产⽣从3、4、5到100的序列。
参考前⾯的内容,我们把主体部分的内容⼀起列出来:#前两项不⽤计算,直接显⽰
print("第 1 项为:",a)
print("第 2 项为:",b)
#从第3项开始,循环到第101项
for i in range(3,101):
c = a + b #计算第三项
a =
b #3个元素的窗⼝向后移,原第⼀个元素被抛弃
b =
c #第⼆个元素更新为新计算的项
print("第",i,"项为:",c) #显⽰
为了看起来更清楚,我们这次使⽤截图来展⽰上⾯程序的输出结果:
程序优化
有⼈说“好⽂章是改出来的。”,其实好的程序也是⼀样。程序编写第⼀项任务是完成需求所定义的基本⼯作。随后就要根据程序的表现,有针对性的优化。程序优化最基本的任务通常是速度和内存的占⽤。因为我们⽬前的学习还⽐较基础,暂时不会涉及到那些部分,所以我们先对程序的结构和代码量进⾏优化。⽬标是结构更清晰易读,代码更精简⾼效。
⾸先我们要根据当前程序的情况进⾏分析评估,根据评估的结果决定下⼀步的改进⽅向。以当前的程序情况来说,可以容易的发现以下⼏项问题:斐波那契数列⽣成的过程中,前两项的⽣成是单独处理的,跟后⾯的98项不统⼀,这会造成将来对程序修改、重⽤的时候,这两项都要单独处理,维护性差。
也因为对头两项单独的处理,多次使⽤了print函数,造成代码冗余。
变量c在显⽰完成后实际可以不⽤保存,没有必要使⽤,这造成内存的浪费。
最后是没有进⾏函数化,可重⽤性差。
根据我们的分析结果,进⾏程序优化之前,我们补充⼀点知识。在第四讲的做练习的时候,为了求甲、⼄双⽅的速度,我们曾经⾃定义⼀个函数,最后求得结果的时候是这样⼀句:#计算原题:当甲⼄双⽅相距36千⽶时双⽅的速度
x,y = getSpeed(36) #getSpeed函数,最后使⽤了return x,y
这种使⽤⽅法很⾃然,跟单独⼀个变量的赋值⽐起来,效率也更⾼。我们在这⾥总结⼀下为变量赋值的⼏种形式:#常规的赋值
a=1
c="abcd"
#多元赋值
x,y = 2,3
x,y = 3,2
x,y = y,x #注意不是数学等式,这是交换两个变量的值
x,y = y,x+b
#连续赋值
a=b=c=d=10 #赋值结束后,变量a/b/c/d都将是10
好了,我们对程序进⾏优化。刚才讲到的多元赋值也能⽤来优化这个程序:"""
使⽤for循环⽣成前100项斐波那契数列
作者:Andrew
斐波那契数列指的是这样⼀个数列 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89...
这个数列从第3项开始,每⼀项都等于前两项之和。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论