流程控制
流程控制以循环为主,旨在让计算机重复的去做某一件事情。
在介绍流程控制一章节前,引入一个叫做遍历的概念:
- 遍历是指对一个可迭代对象类型(暂时理解为容器类型),进行数据项的依次访问行为
下面这个是遍历行为轨迹示意:
# [1, 2, 3, 4, 5, 6]
# ------------------>
重复的取值也在遍历范畴:
# [1, 2, 3, 4, 5, 6]
# ----->
# <--
# -------->
# <---
# ------->
条件循环
while
while循环是基于条件的循环,while本身具有if判断的功能,当条件为真时开始重复执行子代码块中的内容直至条件为假后跳出循环。
tag = 10
while tag > 5:
print("current tag value : %s" % tag)
tag -= 1
print("while cycle end tag of value : %s" % tag)
# current tag value : 10
# current tag value : 9
# current tag value : 8
# current tag value : 7
# current tag value : 6
# while cycle end tag of value : 5
条件退出
while只有在每一次的循环开始前才会检测条件是否为真,如果条件在子代码块内部发生改变则本次的循环并不会立即退出,如下所示:
tag = 10
while tag != 5:
print("current tag value : %s" % tag)
tag = 5
print("no stop continue to run")
print("while cycle end tag of value : %s" % tag)
# current tag value : 10
# no stop continue to run"
# while cycle end tag of value : 5
while/else
- 正常结束的while循环是指不被强制break的while循环
tag = 3
while tag:
print(tag)
tag -= 1
else:
print("else...")
# 3
# 2
# 1
# else...
死循环
当while的结果永远为真时,将引发死循环。
单纯的死循环不会引来性能损耗问题,但是如果做一些计算操作则必将会对cpu带来极大的性能压力,因为cpu没有一刻的休息时间。
tag = 1
while 1:
tag += 10
取值循环
for
for循环内部是基于while循环来完成的,for循环在对可迭代对象的取值上比while循环更加的方便,故也被称为取值循环。
for循环常用于遍历可迭代对象进行取值操作,以下是语法介绍:
for 迭代变量 in 可迭代对象(暂时可理解为容器类型)
逻辑操作...
以下是使用while循环遍历可迭代对象进行取值,相当麻烦:
lst = [1, 2, 3, 4, 5]
index = 0
while 1:
try:
print(lst[index])
except IndexError:
break
index += 1
# 1
# 2
# 3
# 4
# 5
如果使用for循环,那么就变的简单许多:
lst = [1, 2, 3, 4, 5]
for i in lst:
print(i)
# 1
# 2
# 3
# 4
# 5
结束退出
lst = [1, 2, 3, 4, 5]
for i in lst:
print(i)
print("for cycle end")
# 1
# 2
# 3
# 4
# 5
# for cycle end
for/else
- 正常结束的for循环是指不被强制break的for循环
lst = [1, 2, 3, 4, 5]
for i in lst:
print(i)
else:
print("else..")
# 1
# 2
# 3
# 4
# 5
# else..
range()
我们有一个需求需要让计算机重复打印5次hello,world,你可能会这样做:
count = 5
while count:
print("hello,world")
count -= 1
也可以使用for循环来进行完成,但是这样会很麻烦,由于使用for循环必须遍历一个可迭代对象,所以要先创建一个可迭代对象:
count = [0, 1, 2, 3, 4]
for i in count:
print("hello,world")
如果你使用range(),这一切都会变得非常简单,range()会帮助你快速的创建一个可迭代对象,我们只需要指定它的次数即可:
for i in range(5):
print("hello,world")
关于range()方法的其他讲解,会在下面进行。
容器遍历
字符串遍历
示例演示:
string = "hello world"
for i in string:
print("index : %s, value : %s"%(string.index(i), i))
# index : 0, value : h
# index : 1, value : e
# index : 2, value : l
# index : 2, value : l
# index : 4, value : o
# index : 5, value :
# index : 6, value : w
# index : 4, value : o
# index : 8, value : r
# index : 2, value : l
# index : 10, value : d
列表遍历
普通遍历:
lst = [1, 2, 3, 4]
for i in lst:
print(i)
通过enumerate()函数来同时遍历2个相同长度的列表:
lst1 = ["A", "B", "C", "D"]
lst2 = ["a", "b", "c", "d"]
for index, item in enumerate(lst1):
lst1Message = str.format(
"lst1 index position {} is data item {}", index, item)
print(lst1Message)
lst2Message = str.format(
"lst2 index position {} is data item {}", index, lst2[index])
print(lst2Message)
通过[::-1]来反向遍历列表:
lst = ["A", "B", "C", "D"]
for i in lst[::-1]:
print(i)
lst = ["A", "B", "C", "D"]
for i in lst[::2]:
print(i)
字典遍历
普通的遍历只会遍历出key,这样的操作等同于遍历dict.keys():
dic = {
"k1": "v1",
"k2": "v2",
"k3": "v3",
}
for k in dic:
print(k)
# k1
# k2
# k3
如果你想取出value,则可以遍历dict.values():
dic = {
"k1": "v1",
"k2": "v2",
"k3": "v3",
}
for v in dic.values():
print(v)
# v1
# v2
# v3
如果你想同时取出key和value,则可以遍历dict.items():
dic = {
"k1": "v1",
"k2": "v2",
"k3": "v3",
}
for k, v in dic.items():
print(k, v)
# k1 v1
# k2 v2
# k3 v3
局部作用域
如果一个迭代变量的命名为i,那么这个迭代变量能在外部访问到吗?答案是能!
其实在Python2和python3中,普通的for循环语句是没有局部作用域这一个说法的,希望在未来版本能有所改进。
for i in range(10):
pass
print(i)
# 9
循环控制
continue
在while/for中均可以使用continue跳过本次循环。
以下用for循环进行举例:
for i in range(5):
if i == 3:
continue
else:
print(i)
# 0
# 1
# 2
# 4
break
在while/for中均可以使用break结束本层循环。
以下用for循环进行举例:
for i in range(5):
if i == 3:
break
else:
print(i)
# 0
# 1
# 2
循环嵌套
while嵌套
while循环支持多层嵌套,在使用时注意下面的事项:
- 如果是使用基于条件退出那么所有的while循环都必须遵循同一个条件才能退出
- break只针对当前的while循环体退出,对于非当前的while循环体不生效
- continue只针对当前while循环体跳过,对于非当前的while循环体不生效。
如下示例:
tag = True
while tag:
print("outer while cycle start, current tag value is : %s" % tag)
while tag:
print("intermediate while cycle start, current tag value is : %s" % tag)
while tag:
print("inner while cycle start, current tag value is : %s" % tag)
tag = False
# outer while cycle start, current tag value is : True
# intermediate while cycle start, current tag value is : True
# inner while cycle start, current tag value is : True
for嵌套
for循环同样支持嵌套。
外层执行1次,内层的for循环要全部循环完成才回到外层执行第2次。
for i in range(65, 68):
print("outer for cycle, current cycle value is : %s" % chr(i))
for j in range(97, 100):
print("inner for cycle, current cycle value is : %s" % chr(j))
print("")
# outer for cycle, current cycle value is : A
# inner for cycle, current cycle value is : a
# inner for cycle, current cycle value is : b
# inner for cycle, current cycle value is : c
# outer for cycle, current cycle value is : B
# inner for cycle, current cycle value is : a
# inner for cycle, current cycle value is : b
# inner for cycle, current cycle value is : c
# outer for cycle, current cycle value is : C
# inner for cycle, current cycle value is : a
# inner for cycle, current cycle value is : b
# inner for cycle, current cycle value is : c
以下是使用for循环打印乘法表的例子:
for i in range(1, 10):
for j in range(1, i+1):
print("%s * %s = %s" % (i, j, i*j), end="\t")
print("")
range()详解
range()
range()方法在Python2中返回的是一个列表,而在python3中返回的是一个可迭代对象(这种可迭代对象不会存值,而是惰性求值,类似于生成器)。
range()方法有三个参数,如下表所示:
参数介绍 | 描述 |
---|---|
start | 从几开始生成 |
stop | 生成到几结束 |
step | 步长间距 |
在使用range()进行生成时,需要注意顾头不顾尾。
如下所示:
lst = list(range(1, 10, 2))
print(lst)
# [1, 3, 5, 7, 9]
xrange()
Python2中的xrange()与python3中的range()相同,均返回可迭代对象,而非列表。
关于为什么做,其实是为了节省内存空间。
列表中的具体值会存在内存中,而如果是一个通过计算可惰性求值的可迭代对象,则不会消耗太大的内存,以下是自定义range()的实现。
class Range:
def __init__(self, stop, start=0, step=1):
self.start = start
self.stop = stop
self.step = step
self.current = None
def __iter__(self):
return Range_iterator(self.stop, self.start, self.step)
class Range_iterator:
def __init__(self, stop, start, step):
self.start = start
self.stop = stop
self.step = step
self.current = self.start
def __next__(self):
if self.current < self.stop:
retDataItem = self.current
self.current += self.step
return retDataItem
raise stopiteration
for i in Range(10):
print(i)
for j in Range(10):
print(j)
实例练习
将列表内的元素,根据位数合并成字典,列表如下:
lst = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 32769, 65536, 4294967296]
答案:
lst = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 32769, 65536, 4294967296]
dic = {}
for i in lst:
k = len(str(i))
# 如果不存在该键,这该键等同于一个空列表
dic.setdefault(k, [])
dic[k].append(i)
print(dic)
使用for循环打印三角形:
for i in range(1, 6):
for j in range(1, 6 - i):
print(" ", end="")
for k in range(1, i + 1):
print("* ", end="")
print("")
# *
# * *
# * * *
# * * * *
# * * * * *
有四个数字:1、2、3、4,能组成多少个互不相同且无重复数字的三位数?各是多少?
count = 0
for i in range(5):
for j in range(1, 5):
for k in range(1, 5):
if (i != k) and (i != j) and (j != k):
count += 1
print(i, j, k)
print(count)
# 36
斐波拉契数列是这样的一个数列:0、1、1、2、3、5、8、13、21、34、……
前2个值加起来的结果恰好等于第3个值,求一个长度为10的斐波拉契数列:
n = 10
fibArray = []
a , b = 0, 1
for i in range(n):
fibArray.append(a)
a, b = b, a + b
print(fibArray)
# [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
输入2个数字,求2个数字的最小公倍数:
x = int(input(">>>"))
y = int(input(">>>"))
minCommonMultiple = None
if x > y:
greater = y
else:
greater = x
while 1:
if ((greater % x == 0 ) and (greater % y == 0)):
minCommonMultiple = greater
break
greater += 1
msg = str.format("{0}和{1}的最小公倍数为{2}", x, y, minCommonMultiple)
print(msg)
输入2个数字,求2个数字的最大公约数:
x = int(input(">>>"))
y = int(input(">>>"))
maxCommonDivisor = None
if x > y:
smaller = y
else:
smaller = x
for i in range(1, smaller + 1):
if ((x % i == 0) and (y % i == 0)):
maxCommonDivisor = i
msg = str.format("{0}和{1}的最大公约数为{2}", x, y, maxCommonDivisor)
print(msg)