![自学Python:编程基础、科学计算及数据分析](https://wfqqreader-1252317822.image.myqcloud.com/cover/254/34659254/b_34659254.jpg)
2.3 判断与循环
判断和循环是程序逻辑的重要组成部分。通过判断和循环,我们可以实现很多复杂的功能。
2.3.1 判断
判断语句(If-Statement)通常基于某种条件触发,当条件满足时,执行一些特定的操作。
1. if语句
Python使用关键字if语句实现判断,最简单的用法为:
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/69_03.jpg?sign=1738867842-o87SMcKQykjkKjuj4pkukIqELQYQbao6-0-317af27a8df88678e50325360e7dedb0)
它包含这样几个部分:
● if关键字,表示这是一条判断语句;
● <condition>表示判断的条件,当这个条件被满足(即条件为真)时,执行<statements>中的代码,条件不满足,<statements>中的代码不会被执行;
● 冒号表示判断代码块的开始;
● <statements>表示条件满足时,执行的代码块。
例如,对于下面的代码:
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/69_04.jpg?sign=1738867842-fFnDUiIH8xX8Z1DZc9EwWQFB70JPbtMa-0-7dc00f1f2f111b01c8ca8febe4b62403)
x满足大于0的条件,所以程序会打印出相关文字。条件不满足时,程序不会执行if代码块中的部分:
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/70_01.jpg?sign=1738867842-6HgPXsxyG4Io5w5i4ofG5fr4q4XlzZUK-0-707056ba355ec033c05b1603d7c5e31a)
当判断语句执行的代码块结束时,之后的代码需要回到判断语句开始时的缩进状态才能继续执行:
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/70_02.jpg?sign=1738867842-kUNozC06PlfWQx7RCA9RreQrEMt3d0tW-0-c4c88d17603fb9c62d2143902eb43558)
x<0的情况:
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/70_03.jpg?sign=1738867842-MlwfwVrWRBW8AViB86bBqCIyUIkDvVS8-0-92a31443941e9f429c9436ba939fca18)
在这两个例子中,最后一句并不是if语句中的内容,所以不管条件满不满足,它都会被执行。
2. elif和else语句
一个完整的if结构通常如下所示:
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/70_04.jpg?sign=1738867842-Z0eC6ypjeiWuFMbsl4MQXD9ldAvxlDFO-0-6405f637c6730100c8bccbf41bd53db9)
关键字elif是else if的缩写。其执行过程为:
● 条件<condition 1>满足,执行if后的代码块,跳过elif和else的部分;
● 条件<condition 1>不满足,跳过if后的代码块,转到第一个elif语句看条件<condition 2>,<condition 2>满足时执行它对应的代码块,否则转到下一个elif;
● 如果if和elif的条件都不满足,执行else对应的代码块。例如:
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/71_01.jpg?sign=1738867842-BwmBRIOCsDe4el4BYBPakHhLEgLap7dG-0-7230c5d3200330c1822e9957ea1e809c)
对于一个if语句,elif的个数没有限制,可以没有,可以有1个,也可以有多个。
例如,不使用elif:
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/71_02.jpg?sign=1738867842-WLHW1CbwNKfwrTZPHeJ1gXYOEHWwklVK-0-8053fa44eb410068e53e23bec47d283f)
使用多个elif:
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/71_03.jpg?sign=1738867842-nGzh0M9QCFgKIfQb77qdTE4WO0EjD6Xm-0-cda42b931a71570c293898b54e2917ab)
else语句最多只有一个,也可以没有,如果出现,要放在所有的if和elif语句后面。
3. 判断条件
我们可以在判断语句中可以使用布尔型变量作为判断条件。事实上,Python对于判断条件没有任何限制,除了布尔型,判断条件可以是数字、字符串,也可以是列表、元组字典等结构。
在Python中,大部分的值都会被当作真,除了以下几种情况:
● False,包括所有计算结果为False的表达式;
● None,包括所有计算结果为None的表达式;
● 整数0值,包括所有计算结果为0的表达式;
● 空字符串,空列表,空字典,空集合,空元组。
浮点数0.0值也会被当作False:
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/72_01.jpg?sign=1738867842-5V2IklnanV3Dog4TyGQIAxp6Lq4Jcz1A-0-08639f7ca4febccd855a37f4a192113a)
但是不推荐使用浮点数作为判断条件,因为浮点数存在精度的问题:
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/72_02.jpg?sign=1738867842-KPBZnsRnfrqef5ujvRlbveTcRFNJI6ov-0-028936f0edd23924429629052f28aaad)
虽然计算的结果是0.0,但是if条件却执行了。
复杂的判断条件可以使用关键字and、or和not进行组合得到,它们分别对应且、或、非的操作:
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/72_03.jpg?sign=1738867842-CsgX2EsScPaMq0QtalEgdgtePnWIVh6g-0-43efc247af986d24533fbbf7b0c25d71)
组合的对象可以不是布尔型:
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/72_04.jpg?sign=1738867842-gaF4MCJxgH7sUigTdoVqvI6BfuHen48X-0-710e7f2899bf3a6c9b87585a5e914c73)
对于关键字and:
● 如果两个值都为真,返回第二个值;
● 如果至少有一个值为假,返回第一个为假的值。
and的返回值是传入的表达式值,而不是True或者False,如:
In [25]: [] and 2333
Out[25]: []
与and相反,对于关键字or来说:
● 如果两个值都为假,返回第二个值;
● 如果至少有一个值为真,返回第一个为真的值。
如:
In [26]: [] or 0
Out[26]: 0
4. 判断的简单实例
我们用判断语句来判断一个年份是不是闰年。
闰年(Leap Year)的定义是这样的:普通年能被4整除且不能被100整除的为闰年,如2016是闰年,2017不是闰年;逢百的世纪年能被400整除的为闰年,如1900年不是闰年,2000年是闰年。
按照上面的逻辑,若年份变量为year,则第一个判断逻辑为:
year % 4 == 0 and year % 100 != 0
第二个判断逻辑为:
year % 400 == 0
为此,我们的程序可以写成:
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/73_01.jpg?sign=1738867842-iH4SO0z4xB2Y5Ppb37WVgc3SKndFClW3-0-e9ffe2ff4495d267a91577dd95dcf8dd)
或者使用关键字or将两个条件合并:
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/73_02.jpg?sign=1738867842-9hErn8xZjf3mHpLSusukiZAnt2wxwGlD-0-826e6ea1a30d33d93104b20274edea68)
关键字and、or、not是有运算先后关系的:先算not,再算and,最后算or。为了避免混淆,我们将第一个and的内容用括号放在了一起(即使这样是多余的),方便看清程序的逻辑。
除了正常的判断语句,关键词if还可以写到一行中:
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/73_03.jpg?sign=1738867842-3H06QoQCfSxEpIAYzhoXBNK76miFkVGR-0-8a2257a5057abc2048d3a25fe55808d4)
if构成了这样的一个表达式:
<value1> if <condition> else <value2>
当条件<condition>满足时,表达式值为<value1>,否则为<value2>。
2.3.2 循环
循环(Loop)的作用是将一段代码重复执行多次。
在Python中,循环结构主要有以下两种结构:while循环和for循环。
1. while循环
while循环的基本形式为:
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/74_01.jpg?sign=1738867842-G1elk1oduv0l3MEMJMM2XPMNTv1AT5sr-0-86f899e95364fc8289ac7a4316440167)
Python执行<statesments>代码块,直到条件<condition>不满足为止。
例如,我们用while循环来计算数字1到99999的和:
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/74_02.jpg?sign=1738867842-Vqdo9CgC6JoW2sGDotTGpdkXiKtSzIev-0-76e1ad47e8a8630e8429f378fc453319)
循环在i等于100000停止。
再如,我们可以用列表作为循环的判断条件,在循环中每次抛出列表中的一个元素,直到列表为空,因为空的列表会被当作False:
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/74_03.jpg?sign=1738867842-Svs1Qd8ALXptfyg9YPLnrRAuzBVtOkob-0-b88d4c01c9d390a8da055784fc5c2018)
2. for循环
for循环是Python中另一种实现循环的形式,其结构为:
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/74_04.jpg?sign=1738867842-smqZaO2O2pVsrugvOuMClIDS27yfstqN-0-f404ece526a14ba65d0c1fc52e599207)
for循环与while循环不同的地方在于,for循环是遍历一个序列<sequence>,每次将遍历得到的值放入变量<variable>中,而while循环则是执行到条件不满足为止。可以被for循环的序列包括有序序列和无序序列。
例如,列表是一种有序序列,所以上面的例子用for循环可改写成:
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/74_05.jpg?sign=1738867842-Ggq8135i3tsRGXemfC3YPQkXiCIsCiXz-0-e1a43ba72440be55c23eab42c76ef4ae)
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/75_01.jpg?sign=1738867842-wLqRUTyEl5ekwuLfQP6V693yDd6oWMl5-0-86ef61f6db040098b766ee10e3245d36)
for循环每次从列表country中取出一个元素,赋给变量c,然后在循环中处理c。for循环在列表中所有的元素都被遍历完时结束。
我们用for循环实现数字1到99999的和的计算:
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/75_02.jpg?sign=1738867842-1VQgBc7K7wjDayduSnNinRNQhPp8kTAp-0-aac8f8299ba0bcf1cce2354643d25aac)
range()函数可以用来生成一个连续的整数列表,其基本用法如下:
● range(stop):生成从0开始到stop-1的整数组成的列表;
● range(start, stop):生成从start开始到stop-1的整数组成的列表;
● range(start, stop, step):生成从start开始到stop-1,间隔为step的整数组成的列表。
几个range()函数的例子:
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/75_03.jpg?sign=1738867842-pudKbBbjNQ9hjRsNh1AOzaahfDek0uZN-0-a16e18c032e1f1436e29277158ffae64)
3. 不同类型序列的for循环遍历
除了列表,其他的序列也支持使用for循环进行遍历。
有序序列,包括字符串、列表、元组等的遍历方式,都是按顺序从第一个元素开始进行遍历,如元组:
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/75_04.jpg?sign=1738867842-IuUhOQQC8SBbenaSZuqA77FD5miQ9Hqu-0-d934c70cd93e8e50f94a9b7697322b7c)
无序序列,如集合、字典等,按照某种设定的内部顺序进行for循环遍历,这种顺序不一定是有序的,如集合:
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/75_05.jpg?sign=1738867842-1dLwXs06gab1i4z9EVMT1idgMx4GusVU-0-9503992958039b3dc97f63be24bc95e1)
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/76_01.jpg?sign=1738867842-8WLuvOj6cqMGCXMe7Rvaz17E8BpQGhw9-0-e62bde6fea207df9ea6d13b817a2c590)
字典的for循环会按照键的某种顺序进行遍历:
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/76_02.jpg?sign=1738867842-3XOAHFhBzkIDfCaM9bWjYfV0NJWIzpjn-0-6c36163f087f6cea2354ad43ebbf44ce)
如果想要同时得到字典的键对应的值,可以使用以下两种方式。
第一种是用索引:
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/76_03.jpg?sign=1738867842-aZgOH5myUNfHDprmMizvpcM8N8QYlbHa-0-e2adcbc5c3910fca3c772a199306646b)
第二种是使用.items()方法进行遍历:
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/76_04.jpg?sign=1738867842-ZGt9LtO7S1zUd8z81KrFSBL5VhtxZ6gs-0-3c53569d1517296b5ebaa2f6ae2b69d6)
事实上,.items()方法返回的值为:
In [23]: values.items()
Out[23]: [(1, 'one'), (2, 'two'), (3, 'three')]
for循环使用多变量赋值机制将键值对分别赋值给了k和v。
4. continue和break
continue和break都是循环中用来执行特定功能的关键字。这两个关键字通常与判断语句一起使用,用来处理循环中的一些特殊情况。在执行某次循环时,如果遇到continue,程序停止执行这次循环,直接开始下一次循环。
例如,在遍历列表时,我们使用continue来忽略所有的奇数值:
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/76_05.jpg?sign=1738867842-QOTNS3mNBznETKPZUaL0VU9V9WfZM7xj-0-63d05eb86597e2f425d0515e393662f0)
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/77_01.jpg?sign=1738867842-Tfw0J1BZBRzawgWvP83a3P04TvqgAEtr-0-8aec53c0c648e0d108d837ca861a1aed)
在循环的过程,如果i为奇数(即除2的余数不为0),continue后面的print语句会被跳过,直接循环下一个i;如果i为偶数,continue语句不会被执行,因此会打印出相应的结果。
在执行某次循环时,如果遇到break,不管循环条件是否满足,也不管序列是否已经被遍历完毕,程序都会从这个地方停止,并跳出循环。
例如,在遍历列表时,当列表中有大于10的值时,停止循环:
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/77_02.jpg?sign=1738867842-1jzYTMzBf3V2xM25EFJaTYIXnRELOv8R-0-5d8b9b338a0c789419e57e37a9137b06)
在循环的过程中,如果i大于10,break语句被执行。
除了for循环,continue和break语句也可以在while循环使用。循环和判断都可以多层嵌套,即判断中可以有新的判断或循环,循环中可以有新的循环,对于continue和break语句来说,它们只对当前的循环有效,对更外层的循环不起作用。
5. 循环中的else语句
while循环和for循环的后面可以跟else语句,这种else语句要和关键字break一起连用。循环后的else语句在break没被触发时执行。
例如,我们在上面的例子中加入else语句:
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/77_03.jpg?sign=1738867842-0zpEhlu44RWfac4BW881QyylHlPZGZYk-0-ae53ed13b0d48887972eeafaa7a37d12)
当break没有被执行时,else语句被执行:
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/77_04.jpg?sign=1738867842-Iw23shKGTrgPKFtHbVNYuSEjCi2S70l9-0-a426784d76ab4737a846f8a8eebbdb1d)
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/78_01.jpg?sign=1738867842-URN5mWV66Tf8CrKO0Zjw9uObhV6JEiOj-0-34035d3583e069cd836ea301fff256f5)
6. 列表推导式
假设我们要得到一组数的平方,一个简单的想法是使用循环实现:
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/78_02.jpg?sign=1738867842-pMtbkfhKmyjJ7OJtDOwaEct2jZ5miohO-0-924607ceaa0723aa9a0a6d5583cf01c8)
Python提供了列表推导式(List Comprehension)的机制,使用更简单的方式来创建这个列表:
In [34]: [x ** 2 for x in values]
Out[34]: [100, 441, 16, 49, 144]
列表推导式的基本形式是使用一个for循环,对序列的元素依次进行操作得到另一个序列。在上面的例子中,这个操作是对values中的每个值进行平方。列表推导式的最后还可以加入判断语句,实现对序列中的元素进行筛选。
例如,只保留列表中不大于10的数的平方:
In [35]: [x ** 2 for x in values if x <= 10]
Out[35]: [100, 16, 49]
字典也可以用推导式生成,只不过要写成“k: v”键值对的形式:
In [36]: {x: x**2 for x in values if x <= 10}
Out[36]: {10: 100, 4: 16, 7: 49}
7. enumerate()和zip()函数
在Python中,enumerate()函数和zip()函数常与for循环一起使用。
for循环会直接遍历容器类型中的元素:
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/78_03.jpg?sign=1738867842-wUECztUQMu1WKEfhGUFVgqBrvkItjQXS-0-70afa1d3c077c13e1c9187cc82a51443)
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/79_01.jpg?sign=1738867842-6LOBOBZnSPDG8TaYy0fAPLYYtQ0sR5x0-0-a599743a699ccc4e2eb483ddfea92bf4)
有时候,我们希望在得到这些元素的同时,也得到相应的位置信息。
Python提供了enumerate()的函数来实现这样的功能,其用法为:
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/79_02.jpg?sign=1738867842-Acz8DOnjp0DinxV9iyKaTHR1R5OiM24G-0-68a1c8cabffa392f9e30cdbe55ababee)
enumerate()函数在for循环的每一轮会将一个(index, value)组成的元组分别传给i和n。如果只需要位置信息,我们可以利用range()函数和len()函数相结合:
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/79_03.jpg?sign=1738867842-v22mOHFUxkQ0Su6dwttQ9tI9xasG3JBX-0-cf3f557fa79ce88cb6a373f83b7d593b)
在for循环中另一个常用的函数是zip()函数,用法为:
zip(seq1 [, seq2 [...]]) -> [(seq1[0], seq2[0] ...), (...)]
它接受多个序列,返回一个元组列表。该列表的第i个元素是一个元组,由所有序列的第i个元素组成:
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/79_04.jpg?sign=1738867842-U94BvuOJ6jchU4uFeeMZ4kBkIGx6aR3b-0-486d58b471a5759972b23cdee9bfba26)
我们可以这样用for循环迭代zip()函数返回的结果:
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/79_05.jpg?sign=1738867842-5Zh0PQvbXa0ZZKifMCNuk2uHq826AGhr-0-f595d6e5e0cc8232b457b2531cc0275e)
对于zip()函数来说:
● 接受的序列可以是列表,也可以是其他类型的序列;
● 可以接受两个或以上的序列;
● 当序列的长度不同时,zip()函数返回的长度与序列中最短的一个相同。
例如,接受第三个序列,字典z:
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/79_06.jpg?sign=1738867842-kKTQSXXa20n2mV4mtDyT3L5pLJWi8Hn0-0-7f7d7eb903d76b9b604e398313f54e1c)
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/80_01.jpg?sign=1738867842-HV6Lv7SFRKnypT71kvyaobNzkML8yq8j-0-1c00de79fc0ba51de22c76509ed5cefc)
如果参数是字典,zip()函数会保留它的键:
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/80_02.jpg?sign=1738867842-ZYkCQuhnvLvetS6sUqOYs3hgeLWuRP9y-0-356aeeca1c32e50566d98eaff11dbd37)