循环、遍历与列表生成式
在先前的学习中,我们已经接触过循环,并且编写过实现遍历的语句,它能简化我们的代码。
在这一章节中,我们将系统的学习循环和遍历相关的内容,以及 Python 中强大的列表生成式,让我们开始吧 ?。
循环
我们之前编写过的这段代码,它使用了 while
循环:
i = 1 # 初始化申明一个变量
while(i <= 3): # 当 i 的值小于等于 3 时
print("这是第 %d 次打印" % i)
i = i + 1 # 让 i 增加,如果没有这一句,将成为死循环
print("循环已完毕!")
while
循环属于“当型循环”,并且在 Python 中,只有当型循环。
当型循环流程图
当程序执行到 while
语句时,会判断是否满足条件,如果满足则执行相应语句(即缩进内的),执行完毕后,会再次判断是否满足条件,如此循环,直到不满足条件时为止。
所以,上面的代码执行的过程是这样的:
在循环内部嵌套 if
语句可以实现更复杂的逻辑,如:
i = 1 # 初始化申明一个变量
while(i <= 3): # 当 i 的值小于等于 3 时
if i == 2:
print("好像这句话我已经是第二次说了")
else:
print("这是第 %d 次打印" % i)
i = i + 1 # 让 i 增加,如果没有这一句,将成为死循环
print("循环已完毕!")
将会输出:
这是第 1 次打印
好像这句话我已经是第二次说了
这是第 3 次打印
循环已完毕!
continue
如果需要跳过某一次循环,可以使用 continue
关键字,如:
i = 1 # 初始化申明一个变量
while(i <= 6): # 当 i 的值小于等于 6 时
if i == 3:
i = i + 1 # 不要忘记自增
continue
else:
print("这是第 %d 次打印" % i)
i = i + 1 # 让 i 增加,如果没有这一句,将成为死循环
print("循环已完毕!")
输出如下:
这是第 1 次打印
这是第 2 次打印
这是第 4 次打印
这是第 5 次打印
这是第 6 次打印
循环已完毕
break
如果需要跳过整个循环,则使用 break
关键字:
i = 1 # 初始化申明一个变量
while(i <= 6): # 当 i 的值小于等于 3 时
if i == 3:
i = i + 1 #
break
else:
print("这是第 %d 次打印" % i)
i = i + 1 # 让 i 增加,如果没有这一句,将成为死循环
print("循环已完毕!")
输出如下:
这是第 1 次打印
这是第 2 次打印
循环已完毕!
无限循环
如何实现一个无限循环呢?如果条件永远满足,循环也就永远不会结束,如:
while 1 > 0:
print("你输入了:", input("输入内容:"))
这样,便实现了一个复读机程序,由于 1 > 0
永远成立,所以将会无限复读。
在终端中,可以使用 Ctrl + C 强制结束
实际上,1 > 0 == True
,我们可以直接用 while True:
表示无限循环。
无限循环在某些时候是很有必要的,但是不要忘了结合 continue
或 break
使用,不然就成了死循环。
遍历
获取复合数据类型中的所有元素,这一过程被称为“遍历”。
假若我们需要获取列表中所有的元素,可以从下标 0
开始递增,依次获取,通过 len
函数获取列表长度以防止越界:
classmates = ['李甜甜', '谭小蝶', '莉莉', '葛蛋蛋']
i = 0
while i print(classmates[i])
i += 1
# 输出:
# 李甜甜
# 谭小蝶
# 莉莉
# 葛蛋蛋
但是如果想对字典 (dict) 或者集合 (set) 进行类似的操作,就不可行了,因为字典得通过键 (key) 访问值,集合更是无序的。
for
这时就有请 for
上场啦,虽然在习惯上我们仍叫它“for 循环”,但在 Python 中,for
被专门设计用于遍历:
classmates = ['李甜甜', '谭小蝶', '莉莉', '葛蛋蛋']
for classmate in classmates:
print(classmate)
# 输出:
# 李甜甜
# 谭小蝶
# 莉莉
# 葛蛋蛋
- 紧跟着
for
后面引用的变量classmate
代表当前所遍历的具体值,其本身类似函数定义中的形式参数,没有实际含义。 - 紧跟着
in
后面的变量classmates
是遍历的目标,即例子中的花名册。
当字典作为遍历的目标时,默认获取的是键名:
classmates = {
'班长': '李甜甜',
'学习委员': '谭小蝶',
'宣传委员': '莉莉',
'体育委员': '葛蛋蛋'
}
for classmate in classmates:
print(classmate)
# 输出:
# 班长
# 学习委员
# 宣传委员
# 体育委员
出于阅读体验,这里将较长的字典换行书写,等价于:
classmates = {'班长': '李甜甜', '学习委员': '谭小蝶', '宣传委员': '莉莉', '体育委员': '葛蛋蛋'}
再结合字典本身的 []
或 get
方法,自然就能获取对应值:
classmates = {
'班长': '李甜甜',
'学习委员': '谭小蝶',
'宣传委员': '莉莉',
'体育委员': '葛蛋蛋'
}
for classmate in classmates:
print(classmate + ':' + classmates[classmate])
# 输出:
# 班长:李甜甜
# 学习委员:谭小蝶
# 宣传委员:莉莉
# 体育委员:葛蛋蛋
values
如果只需要遍历值,可以这样:
classmates = {
'班长': '李甜甜',
'学习委员': '谭小蝶',
'宣传委员': '莉莉',
'体育委员': '葛蛋蛋'
}
for classmate in classmates.values():
print(classmate)
# 输出:
# 李甜甜
# 谭小蝶
# 莉莉
# 葛蛋蛋
使用遍历的目标的 values()
方法,可以直接遍历键值对的值。
items
如果需要同时遍历一对键和值,可以使用遍历的目标的 items()
方法:
classmates = {
'班长': '李甜甜',
'学习委员': '谭小蝶',
'宣传委员': '莉莉',
'体育委员': '葛蛋蛋'
}
for position, classmate in classmates.items():
print(position + ':' + classmate)
# 输出:
# 班长:李甜甜
# 学习委员:谭小蝶
# 宣传委员:莉莉
# 体育委员:葛蛋蛋
格式为 for key, value in dict.items()
。
range
假如我们需要一个 [1, 2, 3, 4, 5, 6, 7, 8]
的列表,数量不多的时候我们还可以直接写出来,要是需要递增到 100、1000 呢?我们当然不可能逐个慢慢地写出来。
这时就需要列表生成式 range
了:
for n in range(0, 101):
print(n)
# 输出:0 1 2 3 4 5 …… 99 100
range(0, 101)
生成了一个从 0
到 100
的列表,range
函数的第一个参数指定开始的数,第二个参数指定结束的后一位的数。
列表生成式的强大之处在于它还可以进行各种运算。
表达式
生成一个 [0, 1, 2, 3, 4, 5, 6]
的列表可以用 range(0, 7)
表示;如果是 [0*0, 1*1, 2*2, ……, 6*6]
呢?
根据已学的内容,我们可以结合 for
循环和列表的 append
方法:
list = []
for n in range(0, 7):
list.append(n * n)
print(list) # [0, 1, 4, 9, 16, 25, 36]
而利用列表生成式可以写的更简练:
list = [n * n for n in range(0, 7)]
print(list) # [0, 1, 4, 9, 16, 25, 36]
[n * n for n in range(0, 7)]
中,for
前面的表达式 n * n
表示生成的元素形式,不要忘了外围有一对中括号 []
。
条件判断
如果我们仅需要保留生成的列表中的偶数,根据已学的内容,可以这样写:
list = []
for n in range(1, 11):
if n % 2 == 0:
list.append(n)
print(list) # [2, 4, 6, 8, 10]
现在可以直接这样:
list = [n for n in range(1, 11) if n % 2 == 0]
print(list) # [2, 4, 6, 8, 10]
- 同上,
for
前面的n
表示生成的元素形式。 -
range(1, 11)
后面的if
语句表示保留元素时的判断条件,这里后面不需要冒号:
。
此处的
if
仅表示过滤条件,不能跟else
连用。
多变量的列表生成式
和前文 for
循环中的 items
部分一样,列表生成式中也支持类似的语法:
classmates = {
'班长': '李甜甜',
'学习委员': '谭小蝶',
'宣传委员': '莉莉',
'体育委员': '葛蛋蛋'
}
list = [position + ':' + classmate for position, classmate in classmates.items()]
print(list) # ['班长:李甜甜', '学习委员:谭小蝶', '宣传委员:莉莉', '体育委员:葛蛋蛋']
命名规范
position
和 classmate
变量只是代表具体生成的元素,当然可以任意取名:
classmates = {
'班长': '李甜甜',
'学习委员': '谭小蝶',
'宣传委员': '莉莉',
'体育委员': '葛蛋蛋'
}
list = [a + ':' + b for a, b in classmates.items()]
print(list)
但如这种无意义的命名,只会增加代码的阅读负担和理解难度,我们仍推荐更具体、表意明确的命名。
小节
在这一章节中,我们较为系统的学习了循环、遍历和列表生成式,相较于其它语言,Python 在这方面的设计可以说非常先进,体现了 Python 的设计哲学:
用一种方法,最好是只有一种方法来做一件事。(There should be one-- and preferably only one --obvious way to do it.)
学习 Python 的过程,同时也是理解 Python 设计哲学的过程 ?。