![自学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=1739163895-411E3k7Kf2dB5Yw2pwRauuOT5VxSTNmK-0-ce499b7804ad8d683286d63d58d47866)
它包含这样几个部分:
● if关键字,表示这是一条判断语句;
● <condition>表示判断的条件,当这个条件被满足(即条件为真)时,执行<statements>中的代码,条件不满足,<statements>中的代码不会被执行;
● 冒号表示判断代码块的开始;
● <statements>表示条件满足时,执行的代码块。
例如,对于下面的代码:
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/69_04.jpg?sign=1739163895-2EO4CJFjtcAZJwuNL3inWhvhaeHz8KlJ-0-2bd6e28bb702030af2f2afaa83449d62)
x满足大于0的条件,所以程序会打印出相关文字。条件不满足时,程序不会执行if代码块中的部分:
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/70_01.jpg?sign=1739163895-iTyuNzQScLgWCpv3PSipZaSCKYusnMsa-0-dec48dbc2f5c6d147007c27960292684)
当判断语句执行的代码块结束时,之后的代码需要回到判断语句开始时的缩进状态才能继续执行:
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/70_02.jpg?sign=1739163895-nwnzJQ0ENxgBnQg0TjZVzbFrRG6uhAFc-0-4a40fa8aaf4008203731b4bbc6328fbe)
x<0的情况:
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/70_03.jpg?sign=1739163895-2wysvqXpRx3Oi7NDInLp3Z4iArmCfxIx-0-58005ae906e022bb08a1d1ba79a2053d)
在这两个例子中,最后一句并不是if语句中的内容,所以不管条件满不满足,它都会被执行。
2. elif和else语句
一个完整的if结构通常如下所示:
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/70_04.jpg?sign=1739163895-m0y7fzm1IEhQ62rG1404mvE5Q8QT53fD-0-7246de9e0b4c5472473e0d978003b413)
关键字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=1739163895-HffxMkTgV4uu0HFiUaK37KnbgVajJiOg-0-c4cdb9b55e9449dbdbdeb3af1652eafe)
对于一个if语句,elif的个数没有限制,可以没有,可以有1个,也可以有多个。
例如,不使用elif:
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/71_02.jpg?sign=1739163895-IEjfmsiMd82JLY6XzfHhCPRv1SEvYXnI-0-9461736edca31be27b66abbb3b7b4ed9)
使用多个elif:
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/71_03.jpg?sign=1739163895-QfN13rD3GhbNIiZhTa8zyc206Lpo3By3-0-c898a487beab58c35d8455d6eea0c5ab)
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=1739163895-TFn8M19OTLjZND5Ph0wpmlDtaVuJnRcC-0-31b214b34e67f494c9daf192385389e8)
但是不推荐使用浮点数作为判断条件,因为浮点数存在精度的问题:
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/72_02.jpg?sign=1739163895-m5NDEfmCeKntvJSuaEgiu4KC8xW0Uuea-0-7da27de0d250ac84eb1fea516971bb95)
虽然计算的结果是0.0,但是if条件却执行了。
复杂的判断条件可以使用关键字and、or和not进行组合得到,它们分别对应且、或、非的操作:
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/72_03.jpg?sign=1739163895-kckijDcDFA2rW60WI8qNNMLci75rgklm-0-f1dfd46347072185fcc1b1ddd832f347)
组合的对象可以不是布尔型:
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/72_04.jpg?sign=1739163895-aiNSjHeyX6ZTFkch3QJzKpxBxLBbhB7w-0-18d19526dff7c71976fd709d34e3bddc)
对于关键字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=1739163895-AhYFhAnM0CELqr4UxRkkqGraeKspDmrI-0-56c0ecbffd549a31c93c317c6c2c97ce)
或者使用关键字or将两个条件合并:
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/73_02.jpg?sign=1739163895-mRrQCg2WMAfsOQ1whXO8KR8pab7EKUzf-0-790db5cbf74f4c5ae6d0dc1f083bd0fb)
关键字and、or、not是有运算先后关系的:先算not,再算and,最后算or。为了避免混淆,我们将第一个and的内容用括号放在了一起(即使这样是多余的),方便看清程序的逻辑。
除了正常的判断语句,关键词if还可以写到一行中:
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/73_03.jpg?sign=1739163895-nuXLilqNB4fUaZbbMsTHCj9whaSS8WmM-0-931669f0d21be131c4c77a02a626a5c9)
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=1739163895-kHHiFUJysBdhRIjz1FsUzF7BTrbsQf8E-0-1f34f773a6a6eb65c8fb0a945c6d1d40)
Python执行<statesments>代码块,直到条件<condition>不满足为止。
例如,我们用while循环来计算数字1到99999的和:
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/74_02.jpg?sign=1739163895-RJrpVAExwrYfpREVbzYLZP8IHpywIqMz-0-883e5fa0c2a396d63d664f548abde997)
循环在i等于100000停止。
再如,我们可以用列表作为循环的判断条件,在循环中每次抛出列表中的一个元素,直到列表为空,因为空的列表会被当作False:
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/74_03.jpg?sign=1739163895-VHuOgiYultj0q1CP0vvzwVIAtSZh4P2g-0-61ce74bd681c084545074baa2dd9407a)
2. for循环
for循环是Python中另一种实现循环的形式,其结构为:
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/74_04.jpg?sign=1739163895-wjAam48xOzAHE0c6JmvlNOvU1Ml9NAZe-0-3f9c38aba1e36f8c84e34b053b706304)
for循环与while循环不同的地方在于,for循环是遍历一个序列<sequence>,每次将遍历得到的值放入变量<variable>中,而while循环则是执行到条件不满足为止。可以被for循环的序列包括有序序列和无序序列。
例如,列表是一种有序序列,所以上面的例子用for循环可改写成:
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/74_05.jpg?sign=1739163895-ERHbuT3dC2UZBMRteI4kaTfBOVFathoS-0-653bf8fd250a48c8b2bf010ff2f8f290)
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/75_01.jpg?sign=1739163895-6O8uM3QCdneFwI746VSGmVga3Oxs7MHO-0-57e2c1f2f9af9d526226215c80ede5ff)
for循环每次从列表country中取出一个元素,赋给变量c,然后在循环中处理c。for循环在列表中所有的元素都被遍历完时结束。
我们用for循环实现数字1到99999的和的计算:
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/75_02.jpg?sign=1739163895-4Se8rkZuKzZ73ZdvlKq3hdiGENsEv7K0-0-efda9e50a412bdb48d725a94776e0fb5)
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=1739163895-zpXAEX67ic7pwGU2YN5Qv8AxHzNDI22U-0-397d64f2c7ceb15309313032c46a02f3)
3. 不同类型序列的for循环遍历
除了列表,其他的序列也支持使用for循环进行遍历。
有序序列,包括字符串、列表、元组等的遍历方式,都是按顺序从第一个元素开始进行遍历,如元组:
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/75_04.jpg?sign=1739163895-58kOuS4qQzWbCTb7dpif4VSyVmUocacq-0-bb7004f0cb1b4dc52d14e7ba94a7ccdc)
无序序列,如集合、字典等,按照某种设定的内部顺序进行for循环遍历,这种顺序不一定是有序的,如集合:
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/75_05.jpg?sign=1739163895-oIXTwsWli7dHpk5Jj8iQoX5oQ21KGTXJ-0-0931ade7364b45f589d688dec6bd73d6)
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/76_01.jpg?sign=1739163895-p2QHy366is1Q2a5hBW96oeT1PaiARZEI-0-3c2e4f880e8088149df1c0af4be840ee)
字典的for循环会按照键的某种顺序进行遍历:
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/76_02.jpg?sign=1739163895-iEwTXqO5dYkbd41C90mNmxwV2GGVmja9-0-3168f4126ad545cf721b2bf43e9df1be)
如果想要同时得到字典的键对应的值,可以使用以下两种方式。
第一种是用索引:
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/76_03.jpg?sign=1739163895-jJHATy5uMZdA4eEhSCWXOFl3tWT53rD1-0-8a773ff4bf20127ec3de955fc2245273)
第二种是使用.items()方法进行遍历:
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/76_04.jpg?sign=1739163895-12WgGD9WaqLQ1jwJnDdWxBoMbBwUWxwb-0-fc41bf2a48aa2829cd027f90c2aa751f)
事实上,.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=1739163895-zCLcnkkK6ia4hTOljjvmUcD6d5hCJuqV-0-fe9009b12c3898430abb38115321e796)
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/77_01.jpg?sign=1739163895-ABKiXLB8oELfPQZ71Eo8PlAMBz3CB91p-0-cd72435e37ec33a18c8abadce6289251)
在循环的过程,如果i为奇数(即除2的余数不为0),continue后面的print语句会被跳过,直接循环下一个i;如果i为偶数,continue语句不会被执行,因此会打印出相应的结果。
在执行某次循环时,如果遇到break,不管循环条件是否满足,也不管序列是否已经被遍历完毕,程序都会从这个地方停止,并跳出循环。
例如,在遍历列表时,当列表中有大于10的值时,停止循环:
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/77_02.jpg?sign=1739163895-tC4apJxFWg2jGRP240oWr9hoPhrtso2j-0-93364e94f6495962e7b408368de5a1a5)
在循环的过程中,如果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=1739163895-6KYtbxEFiXpOnOcNf4EqwaFqst39DTTR-0-cdc016cf4ea341803e4ccd74d0914df6)
当break没有被执行时,else语句被执行:
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/77_04.jpg?sign=1739163895-15cJuUeN29z3CedtFGBmsna93rkHsmPC-0-484a4e8bcb4888e83ed318d3b0cc9a61)
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/78_01.jpg?sign=1739163895-bMeYshaPDgR8tzboHJFw9RxL8EyIkoBA-0-0f2d323fbc1a23134417ee3ba6ee9ad8)
6. 列表推导式
假设我们要得到一组数的平方,一个简单的想法是使用循环实现:
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/78_02.jpg?sign=1739163895-p179SBbSAV8JZOxRuyzWstmZ1Vvyg4N5-0-8ae8dd4ef8444c5a069c9d7e682150a8)
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=1739163895-mnMZxuwFVzDRjoogHPqtxgWNdJDsHByf-0-e976c4c66f8d1a06133263cfb7a67801)
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/79_01.jpg?sign=1739163895-xmb7wDjtsdfF7GpN1xjFkp1OTAKSflLD-0-c0094bb09175e713022ec9e66e080c33)
有时候,我们希望在得到这些元素的同时,也得到相应的位置信息。
Python提供了enumerate()的函数来实现这样的功能,其用法为:
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/79_02.jpg?sign=1739163895-BpdCw6pIABPoGhghHBHQEE5hm15EuuLg-0-fda8bf740093dbe52248739a46fbadbe)
enumerate()函数在for循环的每一轮会将一个(index, value)组成的元组分别传给i和n。如果只需要位置信息,我们可以利用range()函数和len()函数相结合:
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/79_03.jpg?sign=1739163895-7OoikRppX12AaOYW4rCBA00dyY5RogkZ-0-e38cd7e1c47d40449dbb208a4d00a067)
在for循环中另一个常用的函数是zip()函数,用法为:
zip(seq1 [, seq2 [...]]) -> [(seq1[0], seq2[0] ...), (...)]
它接受多个序列,返回一个元组列表。该列表的第i个元素是一个元组,由所有序列的第i个元素组成:
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/79_04.jpg?sign=1739163895-IxLs6hsv55ZCW4VmQlDrO8A9H0nk8BQR-0-f400ca9ccee7517012800a7e8870aa9e)
我们可以这样用for循环迭代zip()函数返回的结果:
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/79_05.jpg?sign=1739163895-s0KNO29L5SJX0TFSYphkWeS1DRbJxAem-0-7616c79633d2ec7aace17341935eb380)
对于zip()函数来说:
● 接受的序列可以是列表,也可以是其他类型的序列;
● 可以接受两个或以上的序列;
● 当序列的长度不同时,zip()函数返回的长度与序列中最短的一个相同。
例如,接受第三个序列,字典z:
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/79_06.jpg?sign=1739163895-oewZWBUhtBN0cr6cGuG1epUZKt7WFdlF-0-8447a93517454fea0abce9a5a8f83aef)
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/80_01.jpg?sign=1739163895-t2vSUhlv66hugPN3Balteh4Nop6O4BLJ-0-8f36655435f3702f0aa28502989cab84)
如果参数是字典,zip()函数会保留它的键:
![](https://epubservercos.yuewen.com/9B8D30/18513172808564606/epubprivate/OEBPS/Images/80_02.jpg?sign=1739163895-4eNkFZmgeTjK9QIoIyi8eMTCzPr9MKwt-0-e7c9827a0324bc6613b2022d1aeaba2c)