Python 基础教程

第一章 Python简介

大家好!我是 AI 大学堂的宋老师,非常开心在这里和各位朋友们见面,我将陪伴大家开启 Python 启航之路,希望各位朋友都可以掌握 Python,实现自己的学习目标!

首先做一下自我介绍,我叫宋伟,AI 大学堂高级讲师,十余年人工智能及大数据开发经验,精通 Python,内部培训 Python 工程师数百人。

千里之行,始于足下,只有把基础打牢,才能更好的利用 Python 去解放双手,提高效率!本次课程是 Python 基础课程,会将 Python 的基础语法逐一的介绍给大家,大家学会之后,可以掌握 Python 编程思维、语法规则,为后续成为爬虫工程师、数据分析师、人工智能算法工程师等打下坚实基础。

 

#1 Python 是什么?

介绍 Python 之前,我们先来介绍下什么是编程语言。

要让计算机为我们干活,需要给计算机下指令,编程语言便是用来编写让计算机干活的指令的语言。

举个做菜的例子,假设现在需要厨师做一道西红柿炒鸡蛋,在这里厨师便相当于计算机,菜谱便相当于给计算机下的指令,计算机依据我们下达的指令来完成某项任务便相当于厨师依据菜谱做出西红柿炒鸡蛋这道菜。

人们通过编程语言给计算机下达指令,计算机一一的响应执行,编程语言可以理解为人与计算机之间沟通的一种语言。

10d1e53fcfcbb797d089a48e4a495d20

Python 就是一种编程语言,它是吉多·范罗苏姆(Guido van Rossum)在 1989 年的圣诞节期间,为了打发时间而编写的一个编程语言。(牛人就是牛人,打发时间的空隙可以开发出一门语言)。

530b86be5e2c16b8415cf69459805b19

之所以选中 Python 作为编程的名字,是因为他是 BBC 电视剧——《蒙提·派森的飞行马戏团》(Monty Python’s Flying Circus)的爱好者。

Python 是一种易于学习又功能强大的编程语言。它提供了高效的高级数据结构,还能简单有效地面向对象编程。Python 优雅的语法和动态类型,以及解释型语言的本质,使它成为多数平台上写脚本和快速开发应用的理想语言。

Python 解释器及丰富的标准库,提供了适用于各个主要系统平台的源码或机器码,这些可以到 Python 官网 https://www.Python.org/ (opens new window)免费获取,并可自由地分发。许多免费的第三方 Python 模块、程序、工具和它们的文档,也能在这个网站上找到对应内容或链接。

Python 解释器易于扩展,可以使用 C 或 C++ 扩展新的功能和数据类型。

近年来,随着人工智能技术及应用的普及,Python 得到了越来越广泛的应用。从 TIOBE 语言排行榜的趋势可见一斑。2018 年以来,Python 在排行榜上一直处于上升的趋势。

afda802ffcce3696f2904ca60f3f17e9

上面我们简要介绍了 Python 是什么,下面我们用一道简单的题目来检验下自己的掌握情况吧:

吉多·范罗苏姆(Guido van Rossum)是在哪一年编写的 Python?

A. 1988

B. 1989

C. 1900

D. 1901

正确答案:B

选A信息提示:正确答案是1989年哦,同学要认真学习哟! 选B信息提示:选择正确哦,Python是1989年被编写出来的! 选C信息提示:正确答案是1989年哦,同学要认真学习哟! 选D信息提示:正确答案是1989年哦,同学要认真学习哟!

下面,我们继续来看下强大的 Python 可以做些什么?

#2 Python 能干什么?

Python 拥有强大的生态,使得它能够在很多领域得到广泛的应用,下图是 Python 可以应用的一些典型的领域。

d4425cd2f4c50b3c70dee0640de4aebb

数据分析和自动化办公:

Python 适用范围非常广泛,各个领域的人群均可以使用 Python 进行数据分析及自动化办公,提高 Excel、Word 等办公必备软件的使用效率,在讯飞 AI 大学堂的培训里,我们也会针对财务和人力员工进行针对性的 Python培训,主要目的是提高大家的工作效率。通过以往举办的培训情况来看,人均工作效率至少提升 10 倍,下图为我们的财务和人力员工在课程中利用 Python 完成的作业展示,大家都表示,之前需要花费 3 天时间去处理的表格,现在只需要 30 分钟就可以完成了!工作效率提升了,加班变少了,竞争力变强了,有了更多升职加薪的机会,心情也变得更好了!!

2459352907e23b71c7f442fcb040c212

网络爬虫:

Python 的另一个广泛应用就是网络爬虫,网络爬虫就是通过程序去获取 Web 页面上自己想要的数据,也就是自动抓取数据,你可以用爬虫去爬取图片,爬取视频等,只要能通过浏览器访问的数据都可以通过爬虫获取,大家经常使用的搜索引擎就是爬虫的典型应用哦,比如大家搜索“讯飞 AI 大学堂”,搜索引擎就会全网搜索讯飞 AI 大学堂相关的词条,最终将“讯飞 AI 大学堂”匹配度较高的网页显示出来,Python 非常适用于爬虫,学习过程也是趣味性很强,非常享受的一个过程,下面这张图就是我们的实习生小蕊爬取豆瓣《我的姐姐》的影评做出的词图,是不是特别精美,你也想跃跃欲试了呢,跟着课程打下良好 Python 基础,实现这些都是分分钟!

243d2490dbb412cdfd61687baf73f24b

Web开发、游戏开发:

学好 Python,也可以进行 Web 及游戏的开发,Python 实现的 Web 开发及游戏开发对新手非常友好,具有易上手、快速开发等优势,就业前景非常广。

e4442bf60cbc87dcece682978700781c

人工智能:

近几年 Python 出圈的主要原因就是人工智能了,Python 是最适合人工智能的一门编程语言,当前,人工智能正处于第三次发展浪潮,人工智能正在像水和电一样融入千家万户,我们现在已经能够感知到人工智能在我们生活中方方面面的应用,手机语音助手、商场的导购机器人、家庭里的智能电器、精通多国语言的翻译机、智慧交通系统、智慧教育、智能医疗,无人驾驶等等,这些都可以通过 Python 语言来实现,掌握了 Python 就掌握了人工智能的敲门砖,顺利进入人工智能行业。

db840008048e9917e9a6a98517c2ae6f

而 Python 不但应用领域广泛,还得到众多大厂的青睐,下图中的 10 家公司都大量地应用 Python 语言进行数据分析、爬虫和 Web 开发,以及人工智能领域的开发,有大量的爬虫工程师、Python 开发工程师等职位。​

ed5d8549250dcde2dfb84f41d86e0821

既然这么多大厂都在大量地使用 Python,所以学好了 Python,不愁找不到好的工作。

介绍完 Python 的众多应用之后,各位小伙儿更想去实现 Python 的哪一个应用呢?

A.数据分析

B.自动化办公

C.爬虫

D.人工智能

E.Web 开发

F.没有明显目标,想学习进行自我提升

(选A-E)非常棒哦,Python 基础是实现该应用的地基,加油学习哦!

(选F)学好Python基础,更好的实现自我提升!

我们接下来一起感受下 Python 之禅(此部分内容是 Python 优于其他编程语言的地方,感兴趣的朋友们可以仔细看下哦)。

#3 Python 之禅

Python 的设计哲学强调代码的可读性和简洁的语法,尤其是使用空格缩进划分代码块。相比于 Java,Python 让开发者能够用更少的代码表达想法。不管是小型还是大型程序,该语言都试图让程序的结构清晰明了。下面的 Python 之禅(The Zen of Python)列出了 Python 所提倡的一些编程理念(进入到 Python 的命令行界面,输入 import this 便可以看到下面的文字)。Python 之禅的内容其实已经超越了编程语言的范畴,它所提倡的一些理念在现实生活中同样适用。

974d48fd5debf75ae2a2808313dc5450

感受完 Python 的魅力之后,我们正式开启 Python 基础语法的学习!

#4 print() 函数

对 Python 编程语言有了基本的了解之后,我们来看如何使用 Python 提供的 print() 函数将内容打印到屏幕上。

我们希望自己永远 18 岁,我们试下下方语句,点击运行:

print(18)

我们看到点击运行之后,屏幕上出现了 18。

我们仔细看左边的这个语句,18 是在 print() 中的,通过 print() 函数将 18 打印出来,print() 函数是 Python 中的信息输出函数,通过 print() 这一指令,将 () 内的内容打印出来。 8539d013a407b63c7f311353551dc1e9

大家可以将 print(18) 这条语句复制到编辑框中,点击运行感受下 print() 函数。

#5 引号的作用

下面,大家可以运行下 print(50+50),结果是 100,由此,我们看到print()函数不仅能够识别数字,还可以识别数学公式,但是有些情况下,我们希望直接将这个数学公式打印出来,这个时候要怎么办呢?在 Python 的世界里,可以巧妙的利用引号(单引号''、双引" "、三引号''' ''')来实现,我们一起来看下方语句:

print('50+50'),点击运行之后,我们看到屏幕上显示的就是数学算式,而两个语句的区别就在于是否添加了引号,特别注意,Python 中所有英文及数字和标点的输入都要是英文状态下的哦!

我们总结一下:

b8e5f3e571aa09d76d860b0c862be6d0

在 Python 中,我们使用引号来直接打印想要输出的信息,如果输出的信息需要经过计算机的处理,则不使用引号,让 print()函数打印出经过计算机运算处理过的信息。

下面,通过一个题目,我们来自测下本部分内容的掌握情况:

下列哪项语句可以输出 2:

A.print(1+1)

B.print(‘1+1’)

选A,恭喜你,引号的作用掌握的很好哦

选B,差一点就正确啦,可以再回顾下上部分内容哦

再次提醒大家,Python 中的括号、引号都要是英文状态下的哦

#6 转义字符

我们点击下方语句:

print("Twinkle, twinkle, little star, How I wonder what you are! Up above the world so high, Like a diamond in the sky. Twinkle, twinkle, little star, How I wonder what you are!")
1

上方语句打印出了《一闪一闪亮晶晶》的英文版本,我们看到歌词并没有按照每句歌词进行分行显示,很难分辨清不同歌词的位置,有什么方法可以使每句歌词分行显示么,当然是有啦!

这就要使用到转义字符\n,大家点击运行下方语句:

print("Twinkle, twinkle, little star, \nHow I wonder what you are! \nUp above the world so high, \nLike a diamond in the sky. \nTwinkle, twinkle, little star, \nHow I wonder what you are!")
1

我们看到加了转义字符之后,歌词就可以按照每句歌词分行显示,而每个分行的位置都是 \n 发挥的作用;而我们也看到本条语句 print() 中的引号是双引号,正如我们上方所介绍的,单引号、双引号、三引号的作用是一致的,但有一点需要大家注意的是,引号的使用是需要对称的,两个引号都是单引号,信息是正确的,一个单引号,一个双引号,程序就会报错啦!

转义字符的使用非常简单,大家可以收藏下方的图片,需要使用转义字符的时候拿出来看一看哦!

40fc87bd95eb50b7b487d8909a5e1b97

#7 小结

本节课程内容就到这里了,我们一起来总结下本节知识点:

71c408974a3ef58c797cb16633e78a5e

#8 课后题

1.下列转义字符中表示换行的是:

A.\a

B.\b

C.\n

D.’

2.下列引号的使用符合规范的是:

A.print(‘盘古开天辟地”)

B.print(‘盘古开天辟地’)

C.print(‘盘古开天辟地’)

D.print(“‘盘古开天辟地’)

3.下列哪一项无法打印出 520:

A.print(‘500+20’)

B.print(‘520’)

C.print(500+20)

D.print(520)

4.实战题目:和盘古打招呼

很久很久以前,天和地还没有分开,宇宙混沌一片。有个叫盘古的巨人,在这个混沌的宇宙之中,他睡了十万八千年。有一天,盘古突然醒了。他见周围一片乌漆嘛黑,他就抡起大斧头,朝眼前的黑暗猛劈过去了。只听一声巨响,一片黑暗的东西渐渐分散开了。缓缓上升的东西,变成了天;慢慢下降的东西,变成了地。

时光一晃来到了新时代,你可以用Python和盘古打个招呼哦,使用 print() 打印出:盘古,你好!

第二章变量

大家好,现在要正式开始第二关内容的学习啦,在正式开始学习之前,我们先来回顾下上一关的内容吧!

b92a22f985550a489205d1a4ed8364b9

上一关的最后,我们通过 print()函数实现了和盘古打招呼,本关我们将通过 Python 的力量去感受女娲补天的奇迹。

我们先来看下方语句:

name = '女娲'
print(name)
1
2

我们看到屏幕上显示的打印效果是:女娲。

大家可能会有疑问,想实现打印出女娲,直接用 print('女娲') 不就可以实现么?

宋老师这里也非常欣慰哦,小伙伴们对第一章内容的掌握程度真的是非常好呢!要继续加油哦!!

但是我们在实际 Python 的使用中,经常会遇到大量重复的语句,如果使用 print() 函数重复输出的话,如果信息出现了低级的错误,或者是信息需要更新,需要进行信息的更改,都需要修改很多遍,当代码数量非常多的时候,容易出现忘记修改信息等问题,这个时候就需要巧妙的利用变量来解决这个问题。

我们看下方语句:

print('女娲补天之后,天地定位,洪水归道,烈火熄灭,四海宁静。')
print('女娲补天之后,天地定位,洪水归道,烈火熄灭,四海宁静。')
print('女娲补天之后,天地定位,洪水归道,烈火熄灭,四海宁静。')
print('女娲补天之后,天地定位,洪水归道,烈火熄灭,四海宁静。')
print('女娲补天之后,天地定位,洪水归道,烈火熄灭,四海宁静。')
1
2
3
4
5

点击运行之后,我们看到显示五段同样的话,“女娲补天之后,天地定位,洪水归道,烈火熄灭,四海宁静。”

这个时候,我们想修改语句,删除掉’洪水归道’ 四个字,大家可以在编译器中,完成 5 段文字’洪水归道’的删除。

print('女娲补天之后,天地定位,,烈火熄灭,四海宁静。')
print('女娲补天之后,天地定位,,烈火熄灭,四海宁静。')
print('女娲补天之后,天地定位,,烈火熄灭,四海宁静。')
print('女娲补天之后,天地定位,,烈火熄灭,四海宁静。')
print('女娲补天之后,天地定位,,烈火熄灭,四海宁静。')
1
2
3
4
5

是不是觉得在做重复性的工作呢,而且一个不小心,就有一条语句忘记删除了,这个时候我们可以使用变量来解决这个问题,我们一起来运行下方语句:

life ='女娲补天之后,天地定位,洪水归道,烈火熄灭,四海宁静。'
print(life)
print(life)
print(life)
print(life)
print(life)
1
2
3
4
5
6

如果我们想删除洪水归道,只需要在变量 life 中删除掉洪水归道即可。

life ='女娲补天之后,天地定位,,烈火熄灭,四海宁静。'
print(life)
print(life)
print(life)
print(life)
print(life)
1
2
3
4
5
6

是不是方便了很多呢,上述语句中的 name 和 life 都是变量,下面我们就一起来认识下变量吧:

#1 什么是变量

在程序设计语言中,变量是存储单元的标示牌,在这块存储单元中,可以存储任何值,我们可以通过变量名来访问存储的值。

ee9bb7e45f903630df40ec1b5f30c6eb

在上图中,age 是内存地址 0X107A5D960 的标示牌,我们可以通过 age 来访问变量的值 18。

在内存中存储值和我们在日常生活用收纳箱来收纳东西是类似的。在下图中,总共有 5 个抽屉,为 5 个抽屉从上到下分别编号 1、2、3、4、5,编号也相当于是抽屉的地址(和内存地址类似), 五个抽屉从上到下分别存储了湿巾、毛巾、配饰、玩具、衣服(物品相当于在内存中存储的值),为了以后取东西快捷,我们会为五个抽屉分别写上存储物品的名字(相当于变量名)。这样以后我们在取东西的时候便可以很快的定位到某个抽屉,进而取出东西。

f18ee7bea185ee8569486e3fd700159d

我们来用 Python 语句表示上述内容:抽屉的英文是drawer,我们将第一层抽屉用 drawer1 表示,第二层抽屉用drawer2 表示……第五层抽屉用 drawer5 表示,再将所放置的物品和抽屉进行一一对应:

drawer1 = '湿巾'
drawer2 = '毛巾'
drawer3 = '配饰'
drawer4 = '玩具'
drawer5 = '衣服'
print(drawer1)
print(drawer2)
print(drawer3)
print(drawer4)
print(drawer5)
1
2
3
4
5
6
7
8
9
10

这些语句中的 drawer1、drawer2、drawer3、drawer4、drawer5 就是变量名称。

上述语句也就是创建五个抽屉变量的过程。

接下来我们详细介绍下 Python 变量的创建。

#2 变量的创建

与其他编程语言不同的是,Python 没有声明变量的命令,首次为其赋值时,才会创建变量。赋值的语法:

ebe220a826df06044d04c73b8e23e221

#2.1 单变量的赋值

#变量name,表示名字,名字是女娲
name = '女娲'  
#变量age,表示年龄,年龄是18
age = 18   
#打印变量name
print(name)
#打印变量age
print(age)
1
2
3
4
5
6
7
8

这个语句中,我们可以看到 name 代表的是名字,age 代表的年龄,变量的名称是和后面要表达的信息内容相匹配的。

我们来运行下方语句:

name = '女娲'
name = '女娲后人'
print(name)
1
2
3

我们看到,打印 name 的结果是女娲后人,并不是女娲了,也就是同一个变量名称,我们对其进行多次赋值的时候,变量会取最后一次的赋值内容。

实践小练习:大家来通过变量打印出自己的名字、年龄和身高吧。

在 Python 的实际应用中,除了简单的单变量赋值外,还会涉及多变量赋值,下面我们就一起来介绍下多变量的赋值。

#2.2 多变量的赋值

在 Python 的应用中,很多情况下,我们需要将同一个值赋给多个变量,下面我们一起来看下一个值是如何赋给多个变量的。在中国民间神话中,女娲在造人之前,于正月初一创造出鸡,初二创造狗,初三创造猪,初四创造羊,初五创造牛,初六创造马,初七这一天,女娲用黄土和水,仿照自己的样子造出了一个个小泥人,她造了一批又一批,觉得太慢,于是用一根藤条,沾满泥浆,挥舞起来,一点一点的泥浆洒在地上,都变成了人。人物 x、人物 y、人物 z 都是女娲造出的泥人,我们将 x、y、z 赋值为泥人,运行下方语句:

#2.2.1 一个值赋给多个变量

x = y = z = '泥人'

print(x)
print(y)
print(z)
1
2
3
4
5

我们看到一个值赋给多个变量的时候,可以用赋值符 = 将多个变量连接,如上方语句 x = y = z,再根据单个变量的赋值方法,将泥人赋值于x、y、z,再通过 print() 函数打印出来。

除了一个值赋给多个变量,Python 中还经常会出现,多个值赋给多个变量的情况,下面我们一起来看这种情况是如何赋值的:

#2.2.2 多个值赋给多个变量

我们运行下方语句:

name,age,weight = '女娲',18,49.99

print(name)
print(age)
print(weight)
1
2
3
4
5

我们看到屏幕输出女娲、18、49.99,我们将女娲赋给变量 name,18 赋给变量 age,49.99 赋给变量weight,根据我们之前所说的内容,变量的命名要能代表值所表达的内容,因此我们知道本条语句的含义是,名字是女娲,年龄是 18,体重是 49.99。

在编程语言中,我们追求代码的规范,而规范代码的表现之一就是变量名简洁有意义,能够让看到该段代码的人理解代码所表示的含义,那么在变量的命名上体现代码规范的一点就是要选择能够代表赋值内容的变量名,一般是赋值内容对应的英文单词,变量的命名除了这一条规则之外,还有一些其他的要求,我们一起来看下:

#3 变量的命名规则

00ccf5852397830778176ce2ad5a42e2

  • 变量名只能包含数字、字母和下划线,也就是只能包含 0-9 、a-z、A-Z 和  _,其余字符都是非法字符。
  • 变量名的开头必须以字母或下划线字符开头,不能以数字开头。
  • 变量名称区分大小写(name、Name 和 NAME 是三个不同的变量)。
  • 如果一个变量名包含多个单词,使用下划线进行分隔,例如:my_name、her_mother 等。
  • 为变量起一个有意义的名字,例如:name 优于 n,这一点就是前面我们强调的代码规范性了,用 n 表示名字,从变量的语法命名规则上来看是没问题的,但是却不符合我们的代码规范,宋老师再次提醒大家,养成一个良好的代码习惯,对于我们进阶成为 Python 大神是很有帮助的哦。

除此之外,Python 中还有一组关键字,这些关键字是保留字,不能用作变量名、函数名或任何其他标识符。关键字列表如下:

cfbb57d2afc8c7624533495767693459

#4 小结

变量的内容我们介绍完成了,我们一起来总结下本部分内容:

babb294d1930bd2ec044b00e1e96ab55

下面,我们来通过一组题目测试下知识点的掌握程度吧!

#5 练习题

1.下列哪个变量名是合法的?

A.na&me

B.2type

C.m@y

D.my_name

2.下列关于变量的命名符合代码规范的是?

A.a = 20

B.weight = 100

C.n = ‘宋老师’

D.xy = ‘你最棒’

3.练习:

创建一个名为 story 的变量,并将 女娲造人的故事 赋给它,最终打印 story 变量。

第三章数据类型

现在我们开始第三关的学习啦,在正式开始之前,我们来回顾下上一关的内容:

babb294d1930bd2ec044b00e1e96ab55-1

上一关中,我们主要介绍了变量、变量的创建及赋值,以及变量的命名规则,我们也提到了 Python 中并没有声明变量的命令,变量的创建是在为其赋值时完成的,这样变量的类型便由值的类型决定。本关我们就来介绍 Python 的数据类型:数字类型、布尔型和字符串类型。

我们先来看一下上关中我们学习过的语句:

name,age,weight = '女娲',18,49.99
print(name)
print(age)
print(weight)
1
2
3
4

我们仔细来看这个语句:

fb74575b1ac58d04c18475190c35d627-1

我们看到,在我们对变量进行赋值时,有的赋值内容有引号,有的没有引号,这其实就是因为这些信息属于不同的数据类型。我们看到数字构成的信息是没有引号的,18 和 49.99 均是由数字构成,都没有引号,就像人类所了解的数学有整数、小数、分数等各种类型一样。在计算机的世界里,也有不同的数字类型,比如 18 就是整数,在 Python 中,我们用 int 来表示整数;49.99 是浮点数,在 Python 中用 float 表示;也就是说,我们人类所理解的整数,在计算机的认知中,是整型 int,而人类所理解的小数,在计算机中则是用浮点型 float 表示。

#1 数字类型

c402a55a0b5d67584eaf4a09c0056eb8

#1.1 int

相传在上古时期,老百姓无法分辨粮食和草药,只能依靠打猎维持生存,即使生病也没办法医治,神农氏因为想改变这个局面,亲自上山采药,亲口尝各类草药,辨别药性。

神农氏踏遍了山野,尝了七七四十九天,发现了麦、稻、谷子、高粱能充饥,并且尝出了 365 种草药,还编写了《神农本草》。

这个故事里面,我们看到了 2 个整数,七七四十九天和 365 种草药:

day = 49
number = 365
print(day)
print(number)
1
2
3
4

根据变量命名规则,我们将整数 49 赋值给变量 day,整数 365 赋值给变量 number。

整数为正数或负数,没有小数,长度不限。

这些都是整数哟!

#光速,每秒30万公里
speed_of_light = 300000   
#地球质量,5.97×10²⁴kg
mass_of_earth = 5970000000000000000000000
#地球最深峡谷的海拔,10994m,因在地下,我们这里用负数表示
altitude_of_mariana_trench = -10994
print(speed_of_light)
print(mass_of_earth)
print(altitude_of_mariana_trench)
1
2
3
4
5
6
7
8
9

宋老师在这里用了比较复杂的变量名称,就是给大家展示下变量名的意义表达,通过下划线 _ 可以将有含义的英文串联起来,做到我们的代码规范哟!

下面我们一起看浮点数:

#1.2 float

浮点数是包含小数的正数或负数,就是我们人类世界中的小数。

比如大家非常熟悉的 π:pi = 3.1415926,π 是特殊字符,不能用作变量名,因此我们这里用谐音 pi 来代替哦!(宋老师时刻不忘提醒大家注意变量的命名规则,大家一定要从基础开始养成好的代码习惯!是受益终身的习惯哦!)

pi = 3.1415926
negative_pi = -3.1415926

print(pi)
print(type(negative_pi))
1
2
3
4
5

#1.3 运算符

我们大家都知道数字涉及到加减乘除、比大小等各种运算,Python 中也有这些运算哦,这就是 Python 的运算符,Python 中运算符包括算术运算符、赋值运算符、比较运算符和逻辑运算符,我们逐一来介绍哈。

5d2d306dc3a802c4ff7f66bc0ce4c4dc

#1.3.1 算术运算符

我们再来回顾下神农尝百草的故事,神农氏踏遍了山野,尝了七七四十九天,发现了麦、稻、谷子、高粱能充饥。

这里面的七七十九天,就可以用算术运算符来表示哦,Python 中用*来表示两数相乘,具体语句是:

day1 = 7
day2 = 7
day = day1 * day2
print(day)
1
2
3
4

我们看到最终打印出的是 49,Python 中的算术运算符,我们收藏下方表格哦!

e609c950fe6d4caa6501fecba1a187e9

每一个运算符,我们都给大家附上了相应的例子,大家可以运行感受下。

#1.3.1.1 +(加) 运算符
a = 1
b = 1

c = 3.14
d = 2.71

print(a + b)
print(c + d)
1
2
3
4
5
6
7
8
#1.3.1.2 -(减) 运算符
a = 1
b = 1

c = 3.14
d = 2.71

print(a - b)
print(c - d)
1
2
3
4
5
6
7
8
#1.3.1.3 *(乘) 运算符
a = 2
b = 1

c = 3.14
d = 2.71

print(a * b)
print(c * d)
1
2
3
4
5
6
7
8
#1.3.1.4 /(除) 运算符
a = 2
b = 1

c = 3.14
d = 2.71

print(a / b)
print(c / d)
1
2
3
4
5
6
7
8
#1.3.1.5 %(取模) 运算符
a = 10
b = 3

print(a % b)
1
2
3
4
#1.3.1.6 **(幂) 运算符
a = 10
b = 3

print(a ** b)
1
2
3
4
#1.3.1.7 //(取整) 运算符
a = 10
b = 3

print(a // b)
1
2
3
4

#1.3.2 赋值运算符

下面,我们一起来看下赋值运算符,在变量的赋值中,我们提到了 = 的含义是赋值,在 Python 中赋值运算符 = 可以和算术运算符进行结合,具体如下表,还是建议大家保存下,有需要的时候方便查看!

0730171341b71002d33ae1490f7b8926

#1.3.2.1 = 运算符

= 运算符和变量的赋值是一样哒。

a = 3

print(a)
1
2
3
#1.3.2.2 +=

神农在品尝了 365 种草药之后,并没有放弃寻找更多草药和粮食的脚步,现在他又新品尝了 30 种草药,你能使用 += 运算符帮他计算出他一共品尝了多少种草药么?

number = 365
number += 30

print(number)
1
2
3
4

其他的赋值运算符,宋老师也都一一给大家准备了示例,大家可以对照示例自己体会下赋值运算符的使用:

(自己动手,丰衣足食!!!小伙伴们,加油!!!)

#1.3.2.3 -=
a = 3
a -= 3

print(a)
1
2
3
4
#1.3.2.4 *=
a = 3
a *= 3

print(a)
1
2
3
4
#1.3.2.5 /=
a = 3
a /= 3

print(a)
1
2
3
4
#1.3.2.6 %=
a = 10
a %= 3

print(a)
1
2
3
4
#1.3.2.7 **=
a = 10
a **= 3

print(a)
1
2
3
4
#1.3.2.8 //=
a = 10
a //= 3

print(a)
1
2
3
4

#1.3.3 比较运算符

在神农品尝的 365 种草药中,假设有 50 种可以作为粮食食用,有 200 种是对人类疾病有益的药材,那么到底是药材的数量多还是粮食的数量多呢,这就涉及到比较啦,在人类的认知中,这种比较非常简单:200 > 50,那么在 Python 的世界中,这种比较是如何表达的呢,比较运算符就可以解决这个问题哦!

food_number = 50
drug_number = 200
print(food_number < drug_number)
1
2
3

因为 200 是大于 50 的,因此 print() 打印的是 True,就是这种比较的结果为真!

比较运算符返回的值是 True 或者 False

下图是一些常用的比较运算符,还是建议各位小伙伴收藏哈!

528494624f1f17094a4647e98f339b1c

#1.3.3.1 ==(等于)

【敲重点】宋老师在这里要和大家重点强调下,“ 比较运算符 和 = 赋值运算符的区别:

b472fe75a250e236b326d647cc2d3248

在我们平时的认知中,等于就是用等号 = 来表达,但是在计算机中,等于要用 2 个等号 “ 来表达,单个等号  = 的含义是赋值哦,这一点,大家要熟记哈!

我们也为大家准备了比较运算符的例子,大家可以逐一体验下:

a = 1
b = 2

print(a == b)
1
2
3
4

a 是 1,b 是 2,显然 a 不等于 b,因此打印的结果是 False

#1.3.3.2 !=(不等于)
a = 1
b = 2

print(a != b)
1
2
3
4

a 是 1,b 是 2,a 不等于 b,因此打印的结果是 True

#1.3.3.3 >(大于)
a = 1
b = 2

print(a > b)
1
2
3
4

a 是 1,b 是 2,a < b,因此打印的结果是 False

#1.3.3.4 <(小于)
a = 1
b = 2

print(a < b)
1
2
3
4

a 是 1,b 是 2,a < b,因此打印的结果是 True

#1.3.3.5 >=(大于或等于)
a = 2
b = 2

print(a >= b)
1
2
3
4

a 是 2,b 是 2,a 等于 b,符合 a 大于或等于 b,因此打印的结果是 True

#1.3.3.6 <=(小于或等于)
a = 2
b = 2

print(a <= b)
1
2
3
4

a 是 2,b 是 2,a 等于 b,符合 a 小于或等于 b,因此打印的结果是 True

#1.3.4 逻辑运算符

神农告诉人们,麦、稻、谷子、高粱等 50 种植物可以作为粮食充饥,蒲公英、黄芪、三七等 200 种植物可以作为药材,现在我们想判断下粮食的数量小于 60 并且药材的品种大于 150,是否是真实的,该如何判断呢?

在 Python 中是通过逻辑运算符 and 来实现的,我们来看下方语句:

food_number = 50
drug_number = 200
print(food_number < 60 and drug_number > 150)
1
2
3

我们看到打印出的内容是 Trueand 运算符表示当 food_number < 60 和 drug_number > 150 都为真时,返回 True,下图是常见的逻辑运算符,大家可以保存下哦!

de3975cc9f3902da89c4a17a9488999e

#1.3.4.1 and
a = 4
b = 8

print(a > 3 and b < 10)
print(a > 3 and b < 6)
1
2
3
4
5

我们看到当 a 赋值为 4,a > 3 为真,b 赋值为 8,b < 10 为真,b < 6 为假,逻辑运算符 and 当   a 和 b 都为真的时候,才会返回 True,因此第一个print() 返回值为 True,第二个 print() 返回值为 False

其他两个运算符的例子大家可以自己运行体验下哈:

#1.3.4.2 or
a = 4
b = 8

print(a > 3 or b < 10)
print(a > 3 or b < 6)
print(a > 5 or b < 6)
1
2
3
4
5
6
#1.3.4.3 not
a = 4
b = 8

print(not(a > 3 or b < 10))
print(not(a > 3 or b < 6))
print(not(a > 5 or b < 6))
1
2
3
4
5
6

#2 布尔型

我们在进行逻辑运算和比较运算的时候,得到的结果为 True 或 False。在 Python 中,用 TrueFalse 表示布尔值。

布尔值可以用 andor 和 not 运算。

#2.1 and 运算:

布尔值的 and 运算就是真真为真,当 and 连接的两个布尔型都是 True 的时候,为 True ,一真一假和两假都为假。

print(True and True)
print(True and False)
print(False and False)
1
2
3

#2.2 or 运算:

布尔值的 or 运算就是假假为假,当 and 连接的两个布尔型都是 False 的时候,为 False ,一真一假和两真都为真。

print(True or True)
print(True or False)
print(False or False)
1
2
3

#2.3 not 运算:

布尔值的 not 运算则表示非,非真就是假,非假就是真!

各位小伙伴加油哦,用我们的慧眼来分辨这大千世界的真真假假!

print(not True)
print(not False)
1
2

#3 字符串类型

我们还是回到这张图片:

8c63cb23edf0f49c0290261ea4e36ec7

通过前面的介绍,我们知道了没有引号的数字类型是整数和浮点数,那么用引号包含起来的数据类型是什么呢?Python中,以单引号 ' 或双引号 " 括起来的任意文本就是字符串啦,上图中 '女娲' 的数据类型就是字符串,大家这里需要注意的是,只要被引号包含的任意文本都是字符串!例如:'123456' "hello world!"' 和 " 不是字符串的一部分,只是一种表示方式。

print('hello world!')
print("hello world!")
1
2

如果字符串横跨多行,可以使用三个单引号或三个双引号将字符串括起来。

三个单引号:

print('''Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.''')
1
2
3
4
5
6

三个双引号:

print("""Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.""")
1
2
3
4
5
6

整型和浮点数可以赋值给变量,字符串也是可以赋值给变量的:

say_hi = "hello world!"

print(say_hi)
1
2
3

宋老师出个题目考考大家,看看大家是否已经灵活掌握了本部分知识:

下列数据类型属于字符串的是:

A.weight = 90

B.gift = ‘鲜花’

C.gift_spend = 300

D.math_grade = 96.5

正确答案:B

选A提示:正确答案为B!引号包含的数据类型是字符串哦! 选B提示:回答正确!引号包含的数据类型是字符串! 选C提示:正确答案为B!引号包含的数据类型是字符串哦! 选D提示:正确答案为B!引号包含的数据类型是字符串哦!

#3.1 索引

中国古人一直有观天象的习俗,通过观天象,来获得对季节、气候、甚至是国家命运的认知。现代,通过科学家们的努力,我们知道了浩瀚宇宙的深邃,知道了八大行星的存在,海王星(neptune),八大行星之一,假设我们在Python 的世界中,可以重见神农,让我们用 Python 的语言为神农介绍下海王星的字母构成吧!这就要运用我们下方为大家介绍的内容:索引。

在 Python 中,字符串中的字符可以通过索引来提取。可以从前往后索引,也可以从后往前索引。

索引语法是:变量[下标],这里的下标是由数字表示,代表所要索引的字符在变量中的位置。

当从前往后索引时,下标从 0 开始。

当从后往前索引时,下标从 -1 开始,如下图所示!

1bb07ea0e9f60956c89bd7a9bc5b6134

star = "NEPTUNE"

print(star[0])
print(star[-1])
print(star[6])
print(star[-7])
1
2
3
4
5
6

大家来自己试一下下面这个题目:

introduce_star = ‘This is the neptune’,将变量中所有的 e 打印出来!

(可以试下从前向后索引,也可以试下从后向前哦)

#3.2 切片

我们看到通过索引,只能提取单个字符,神农说,难得来一趟,想多认识一些字符,这个时候怎么办呢?我们可以通过切片来提取变量的多个字符,我们一起来看下切片怎么使用。

切片语法是:变量[头下标:尾下标](不包括尾下标对应的元素)。

当不指定头下标和尾下标时,获取的是整个字符串:star[:]

当只指定头下标时,获取的是从头下标到字符串结尾的所有字符。

当只指定尾下标时,获取的是字符串的开头到尾下标的字符串(不包括尾下标对应的元素)。

头下标和尾下标也可以使用负值。

大家先在心中想一下下方语句的运行结果,再运行一下,看看结果是否一致呢?

star = "NEPTUNE"

# 获取 NEP
print(star[0:3])
# 获取 NEPTUNE
print(star[:])
# 获取 NE
print(star[-7:-5])
# 获取 EPTUNE
print(star[1:])
# 获取 NEPT
print(star[:4])
1
2
3
4
5
6
7
8
9
10
11
12

#3.3 字符串长度

神农:“现代社会真神奇啊,不仅能认识海王星,还能读取海王星的另一种语言表达,可是我还有一个疑问,海王星的英文是几个字母构成的呢”?

我们:“这个问题简单,Python 中 len() 可以获取字符串的长度哦”

star = "NEPTUNE"

print(len(star))
1
2
3

在 Python 中,我们使用 len(变量名) 来获取变量的长度,len 是长度 length 的前三个字母,也是比较好记忆和理解的!

#3.4 字符串方法

Python 有一组可用于字符串的内置方法,可以实现字符串的各种变换,宋老师在这里还是建议大家收藏下方表格哟!

2032d3e6ee68e15283828b434fb68673

#3.4.1 strip() 删除开头和结尾的空白字符

神农:“现代的信息技术太精彩了!”

我们:“这都不算什么哟,还有更精彩的,同样的NEPTUNE(海王星),我们也可以做出一些变换的哦”

神农:“哦?快快,教教我是怎么做的”

有些时候,我们会在代码的编写中做一些空格的操作,这些空格在 Python 中就是空白字符,我们可以使用

strip()来删除字符串开头和结尾的空白字符,使用方法就是变量名.strip(),我们来看下方语句:

star = " NEPTUNE "

print(star)
print(len(star))
print(star.strip())
print(len(star.strip()))
1
2
3
4
5
6

我们看到在没有删除开头和结尾的空白字符串之前,变量 star 的长度是 9,使用 strip() 之后,长度是 7,空白字符串被删除了!

神农:“真是很神奇啊!”

其余方法的使用是一样的,都是变量.方法,下方的几个方法大家自己运行体会下哈!

#3.4.2 lower() 返回小写的字符串

star = "NEPTUNE"

print(star.lower())
1
2
3

#3.4.3 upper() 返回大写的字符串

star = "neptune"

print(star.upper())
1
2
3

#3.4.4 replace() 用另一段字符串来替换字符串

say_hi = "Hello World!"

print(say_hi.replace("World", "Kitty"))
1
2
3

#3.4.5 split() 按指定的分隔符分隔字符串

say_hi = "Mercury,Venus,Earth,Mars,Jupiter,Saturn,Uranus,Neptune,Pluto"

print(say_hi.split(","))
1
2
3

#3.4.6 使用 in 或 not in 来检查字符串中是否存在特定短语或字符

book_name = "Men Are from Mars, Women Are from Venus"

is_exist = "Mars" in book_name
print(is_exist)
1
2
3
4
book_name = "Men Are from Mars, Women Are from Venus"

is_exist = "Mars" not in book_name
print(is_exist)
1
2
3
4

#3.4.7 使用 + 运算符对字符串进行拼接

first_part = "Men Are from Mars"
second_part = "Women Are from Venus"

print(first_part + ', ' + second_part)
1
2
3
4

#3.4.8 字符串中引用变量的值

  • 在字符串前面加小写字母 'f'
  • 在字符串中,将需要引用的变量,用花括号包起来 {name}
name = 'Earth'
age = 4.543E9

print(f"My name is {name}, {age} years old")
1
2
3
4

#3.5 转义

在第一章中,我们曾经给大家介绍过转义字符,今天在进行字符串知识的学习之后,我们再给大家仔细介绍下转义字符中的 \

首先,我们先来回顾下字符串的一个要点,字符串是由单引号 ' 或双引号 " 括起来的任意文本。也就是说,在字符串的变量赋值中,是包含单引号或双引号的,那么对于有些语句本身就包含引号的,Hi, shennong, this ‘s the neptune! 这种情况 Python 是怎么处理的呢?

在 Python 中,对于本身带有引号的字符串,有以下几种情况:

(1)由双引号 " 括起来的任意文本包含单引号 ' ,例如:

print("You're uinique, nothing can replace you.")
1

运行起来,并不会出现问题,正常打印出字符串。

(2)由单引号 ' 括起来的任意文本包含双引号 ",例如:

print('The man who has made up his mind to win will never say "impossible".')
1

运行起来,也都是正确的,但是当我们把上述例子中的双引号 " 换成单引号 ',把单引号 ' 换成双引号 " 时,便会报错。这个时候就需要对 ' 或 " 进行转义:

print('You're uinique, nothing can replace you.')
print("The man who has made up his mind to win will never say "impossible"")
1
2

(3)单引号括起来的字符串中使用单引号,对字符串中的单引号进行转义,使用转义字符\,在每一个字符串中的单引号前使用\

print('You\'re uinique, nothing can replace you.')
1

(4)双引号括起来的字符串中使用双引号,需要对字符串中的双引号进行转义,转义使用字符 \,在每一个字符串中的双引号前使用\

print("The man who has made up his mind to win will never say \"impossible\"")
1

#4 获取数据类型和数据类型转换

神农:“这趟来的太值了,我认识了整型 int、浮点数 float、还有布尔值和字符串,可是怎么我感觉还是有些晕啊,尤其是遇到整数的数字时,到底哪些是整型?哪些是字符串呢?”

我们:“神农前辈不要担心,这个 Python 也有办法解决哦!”

在 Python 中,对于有些变量的数据类型,我们不太确定的时候,可以使用 type(),来获取变量的数据类型,type() 的使用方法是 type(变量名),我们一起来看下面的例子:

#变量weight1,赋值为整数50
weight1= 50
#变量weight2,赋值为字符串50
weight2 = '50'
#变量weight3,赋值为浮点数50.00
weight3= 50.00
#打印变量weight1的数据类型
print(type(weight1))
#打印变量weight2的数据类型
print(type(weight2))
#打印变量weight3的数据类型
print(type(weight3))
1
2
3
4
5
6
7
8
9
10
11
12

我们看到分别打印出了整型、字符串和浮点数。

在 Python 中,不同的数据类型是可以互相转换的,通过类型转换函数来实现,下图为常见的类型转换函数:

e76c18c076a04c5b9e8423fd8825ae17

我们可以使用 int(),将 50.00 转换为 50,也可以使用 float(),将 50 转换为 50.00,具体语句如下:

weight1= 50
weight3= 50.00
weight4= int(weight3)
weight5=float(weight1)
print(type(weight1))
print(type(weight3))
print(type(weight4))
print(type(weight5))
1
2
3
4
5
6
7
8

神农:“嗯嗯,真是太精彩了,变幻无穷!”

我们:“和我们一起学 Python 吧!”

下面,我们运用str() 和字符串的+运算符打印出下列内容:

神农每天品尝 3 种草药,品尝了 50 天,一共品尝了 150 种草药

num1 = 3
num2 = 50
num3 = 150
print('神农每天品尝 '+str(num1)+' 种草药,品尝了 '+str(num2)+' 天,一共品尝了 '+str(num3) + ' 种草药')
1
2
3
4

#5 小结

16280438213964907

#6 练习题

#6.1 将 x 转换成浮点数,并进行输出

x = 5
1

#6.2 将 x 转换成整数,并进行输出

x = 5.5
1

#6.3 获取字符串 str 的长度,并进行输出

str = "Hello World!"
1

#6.4 获取字符串 str 的第一个字符 H,并进行输出

str = "Hello World!"
1

#6.5 获取字符串 str 的子字符串 llo,并进行输出

str = "Hello World!"
1

#6.6 去除字符串 str 中的空格,并进行输出

str = "  Hello World!  "
1

第四章流程控制

今天,我们要进入到第四关内容的学习,流程控制!

在流程控制内容开始之前, 我们一起来回顾下上一关内容:

16280438213964907-1

我们一起进入本次课程内容的学习。

我们一起来了解下牛郎织女的故事:

传说古代天帝的孙女织女擅长织布,每天给天空织彩霞。她讨厌这枯燥的生活,就偷偷下到凡间,私自嫁给河西的牛郎,过上男耕女织的生活。此事惹怒了天帝,把织女捉回天宫,责令他们分离,只允许他们每年的农历七月七日在鹊桥上相会一次。

织女因为厌烦了每天织布的枯燥生活,选择下到凡间。

在我们的生活中,也经常要做大大小小的各种决策。影响我们做出决策的因素有很多,一般是当某些条件满足时,我们会做出决策 A;条件不满足时,做出决策 B。就比如像织女一样,因为感觉到每天织布,生活枯燥乏味,做出了下到凡间的决策;如果生活不枯燥,织女做的决策可能就是还留在天宫快乐地生活。

计算机的执行过程也是类似的,计算机不一定都是从上到下逐条执行指令,有些时候计算机也会对一些条件进行评估,当评估结果为 True 时(满足某些条件),执行某个代码块;当评估结果为 False 时(不满足某些条件),执行另一个代码块。在 Python 中,可以使用 if ... else 语句来完成上述代码流程的控制。

比如:织女厌烦了每天织布的枯燥生活,选择下到凡间。就可以用 if 语句来实现:

# 织女的生活状态是厌烦了每天织布的枯燥生活
living_conditions = '织女厌烦了每天织布的枯燥生活'
if living_conditions == '织女厌烦了每天织布的枯燥生活':
    print('织女下到凡间')
1
2
3
4

#if 语法

#1.1 if

a2c3335611b91e2b391b23865b84c370

我们一定要注意语法规范:if 条件语句后面要加 :,且是英文状态下的冒号 :if 后的语句要缩进四个空格,这是因为语句块 1 是在满足 if 条件下要执行的,因此要有缩进。

织女下凡之后,认识了牛郎,也更加注重身材管理,我们通过 if 条件语句来帮助织女更好地进行身材管理吧!

现在我们假设织女的身高是 1.55 米,体重是 65 公斤,通过 BMI 的计算公式,计算出 BMI,依此来判断织女是否超重。

weight = 65
height = 1.55

BMI = float(weight) / (float(height) * float(height))
if BMI >= 25:
    print("BMI=", BMI)
    print("织女体重过重")
1
2
3
4
5
6
7

我们首先来看上面语句中需要注意的两点:

  1. 不要忘记 if 语句后面的冒号:,如果不带冒号会报语法错误。
  2. Python 语言通过缩进来标识代码块,在上述例子中,print("BMI=", BMI) 和 print("织女体重过重") 属于同一个代码块,当 if 语句的条件成立时,print("BMI=", BMI) 和 print("织女体重过重") 都会被执行。通过缩进来指定代码块是 Python 的一大特色。

织女每天严格控制体重,但是她希望对自己的体重情况有更清晰的认识,而不是仅仅知道自己的体重是否超重?这个时候我们就可以通过 if...else... 来帮助织女啦!

我们一起看下 if...else... 的语法规则:

#1.2 if...else

e78a03c0e7cea1ce6035743e05fbf798

我们来进行稍微精细一点的划分,帮助织女更好的掌握自己的体重情况:

织女在知道自己体重过重之后,非常沮丧,沮丧之后重振旗鼓,执行了非常严格的饮食管理和运动,并且咬牙坚持了很长一段时间,终于体重瘦到了 40 公斤,下面我们用 if...else... 语句来帮助织女判断现在她的身材状态:

weight = 40
height = 1.55

BMI = float(weight) / (float(height) * float(height))
if 18.5 <= BMI < 25:
    print("BMI=", BMI)
    print("织女体重正常")
else:
    print("织女体重过重或过轻")
1
2
3
4
5
6
7
8
9

大家一定要记得 if 后面的冒号和 else 后面的冒号,以及 if 条件下的语句块和 else 下的语句块的缩进哟!织女看到结果后,不清楚自己的体重到底是过重还是过轻,我们有什么办法可以帮助她进一步判断么?这个当然有啦!我们可以使用 if...elif...else 语句来解决!

#1.3 if...elif...else

087ee819bae3affccdf97c3256705010

elif 语句块可出现一次或多次。

下面我们针对织女的需求,进行体重过重和过轻的进一步区分:

weight = 40
height = 1.55

BMI = float(weight) / (float(height) * float(height))
if 18.5 <= BMI < 25:
    print("BMI=", BMI)
    print("织女体重正常")
elif BMI < 18.5:
    print("BMI=", BMI)
    print("织女体重过轻")
else:
    print("BMI=", BMI)
    print("织女体重过重")
1
2
3
4
5
6
7
8
9
10
11
12
13

由于 elif 语句块可出现多次,我们还可以进行细分,帮助织女更详细的掌握自己的体重情况。

weight = 40
height = 1.55

BMI = float(weight) / (float(height) * float(height))
if BMI < 15:
    print("BMI=", BMI)
    print("织女非常严重的体重不足")
elif 15 <= BMI < 16:
    print("BMI=", BMI)
    print("织女严重体重不足")
elif 16 <= BMI < 18.5:
    print("BMI=", BMI)
    print("织女体重过轻")
elif 18.5 <= BMI < 25:
    print("BMI=", BMI)
    print("织女体重正常")
elif 25 <= BMI < 30:
    print("BMI=", BMI)
    print("织女体重过重")
elif 30 <= BMI < 35:
    print("BMI=", BMI)
    print("织女中等肥胖")
elif 35 <= BMI < 40:
    print("BMI=", BMI)
    print("织女严重肥胖")
else:
    print("BMI=", BMI)
    print("织女非常严重肥胖")
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

#1.4 嵌套 if 语句

由于 if 语句允许嵌套,也就是 if 语句中可以再包含 if 语句,需要注意的是相应的语法规则要对应上(比如 if 语句的冒号、缩进、else 的冒号和缩进等等),所以上述 if 语句后面跟的语句块同样可以包含 if 语句。使用嵌套 if 语句,可以将上述代码改成如下形式:

weight = 40
height = 1.55

BMI = float(weight) / (float(height) * float(height))
if 18.5 <= BMI < 25:
    print("BMI=", BMI)
    print("织女体重正常")
elif BMI < 18.5:
    print("BMI=", BMI)
    if 16 <= BMI:
        print("织女体重过轻")
    elif 15 <= BMI < 16:
        print("织女严重体重不足")
    else:
        print("织女非常严重的体重不足")
else:
    print("BMI=", BMI)
    if BMI < 30:
        print("织女体重过重")
    elif 30 <= BMI < 35:
        print("织女中等肥胖")
    elif 35 <= BMI < 40:
        print("织女严重肥胖")
    else:
        print("织女非常严重肥胖")
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

我们看到一共有3个 if...elif...else 语句,根据对齐位置判断语句间的关系,这里要再次强调,使用 if 语句的时候,一定不要忘记缩进和冒号哦!

今天的内容就介绍这里啦,我们一起来回顾下:

#2 总结

6722c9aad098c36743c2779372a51ddf

本节内容,我们主要介绍了流程控制 if 语句、if...else 语句、if...elif...else 语句以及嵌套if语句的用法,在使用这些语句的过程中,我们一定要注意冒号和缩进是不能忘的哦!还有所有的代码都要是英文状态下的哦。

#3 练习题

牛郎织女坚贞的爱情感动了喜鹊,无数喜鹊飞来,用身体搭成一道跨越天河的喜鹊桥,让牛郎织女在天河上相会。下面我们使用 if 语句来判断下鹊桥的长度吧:

如果喜鹊数量小于 1000 只,鹊桥长度为 1 米;喜鹊数量大于等于 1000 只,小于 10000 只,鹊桥长度为 10 米;喜鹊数量大于等于 10000 只,小于 100000 只,鹊桥长度为 100 米;喜鹊数量大于等于 100000只,鹊桥长度大于 100 米!

假定喜鹊数量有四种情况,500只、6000只、20000只、150000只,通过修改喜鹊数量的值来判断鹊桥长度吧!

第五章列表

上一关内容我们给大家分享了条件控制 if 语句,我们一起来回顾下:

6722c9aad098c36743c2779372a51ddf-1

下面我们将开启本关内容的学习:

八仙过海是一个中国民间故事,讲了汉钟离、张果老、韩湘子、铁拐李、吕洞宾、何仙姑、蓝采和和曹国舅八位神仙各显神通渡海的故事。

我们都知道变量只能被赋值为一个值,现在我们想把八位神仙的名字同时赋值,该如何实现呢?

在 Python 中,我们可以通过列表来实现。

列表是有序数据的集合。定义的语法是使用方括号 [] 括起来以逗号分隔的数据。例如:

eight_immortal = ['汉钟离', '张果老', '韩湘子', '铁拐李', '吕洞宾', '何仙姑', '蓝采和', '曹国舅']

print(eight_immortal)
1
2
3

eight_immortal 就是一个列表,[]包含的每一个信息称为元素,’汉钟离’、’张果老’、’韩湘子’等就是元素。

在 Python 中,列表有如下特性:

5a6eeedf2226aeeab50912ca863b5e50

#1 有序

列表不仅是数据的集合,而且这些数据还是有序的。

如果两个列表包含的元素相同,但是元素的排列顺序不同,那么他们是两个不同的列表。

eight_immortal1 = ['汉钟离', '张果老', '韩湘子', '铁拐李', '吕洞宾', '何仙姑', '蓝采和', '曹国舅']
eight_immortal2 = ['吕洞宾', '何仙姑', '蓝采和', '曹国舅', '汉钟离', '张果老', '韩湘子', '铁拐李']

print(eight_immortal1 == eight_immortal2)
1
2
3
4

在上述例子中的两个列表,虽然包含的元素相同,都是八仙的名字,但是元素的顺序不同,所以是不同的两个列表。

#2 元素的数据类型

同一个列表可以包含不同类型的数据。

eight_immortal = ['汉钟离', 1, '张果老', 2, '韩湘子', 3, '铁拐李', 4,'吕洞宾', 5, '何仙姑', 6, '蓝采和', 7, '曹国舅', 8]

print(eight_immortal)
1
2
3

例子中的列表既包含字符串类型的数据也包含整数类型的数据。

这里大家还是要记得用引号包含的数据类型是字符串哦!

#3 元素可重复

eight_immortal1 = ['铁拐李', '铁拐李', '何仙姑', '何仙姑', '蓝采和', '蓝采和']

print(eight_immortal1)
1
2
3

在上面的例子中,'铁拐李', '何仙姑', '蓝采和' 这三个元素是重复的。

#4 元素访问

八仙兴高采烈地来到蓬莱阁上聚会饮酒。酒至酣时,铁拐李意犹未尽,对众仙说:“都说蓬莱、方丈、瀛洲三神山景致秀丽,我等何不去游玩、观赏?”众仙激情四溢,齐声附和。吕洞宾说:“我等既为仙人,今番渡海不得乘舟,只凭个人道法,意下如何?”众仙听了,欣然赞同,一齐弃座动身而去。

我们现在想从列表 eight_immortal 中提取出建议游玩三神山的铁拐李,要怎么操作呢?

大家可以一起回想下在介绍字符串时,介绍给大家的访问字符串中某一个字符的方法——索引,

我们可以通过索引的方式来访问列表中的元素,这个和访问字符串中的字符的原理是一样的。从前往后访问时,索引的下标从 0 开始。

我们看下 eight_immortal 这个列表的八仙的各个位置:

9fda723359b24814dad110d3ca933460

我们想要访问铁拐李,铁拐李的下标位置是3,我们只需要使用索引的方式:列表名[下标],也就是eight_immortal[3] 就可以了,我们一起来验证下,点击运行:

eight_immortal = ['汉钟离', '张果老', '韩湘子', '铁拐李', '吕洞宾', '何仙姑', '蓝采和', '曹国舅']
print(eight_immortal[3])
1
2

下面的语句,大家在点击运行前,先自己判断下访问的是八仙中的哪一位呢?再运行,对比下结果!

eight_immortal = ['汉钟离', '张果老', '韩湘子', '铁拐李', '吕洞宾', '何仙姑', '蓝采和', '曹国舅']
print(eight_immortal[0])
print(eight_immortal[4])
print(eight_immortal[7])
1
2
3
4

和访问字符串中的字符一样,我们还可以从后往前访问,当从后往前访问时,索引的下标从 -1 开始。

2c880a65ec6e296db92a522e1dcc7808

使用从后往前的索引,我们访问铁拐李的语句是:

eight_immortal = ['汉钟离', '张果老', '韩湘子', '铁拐李', '吕洞宾', '何仙姑', '蓝采和', '曹国舅']
print(eight_immortal[-5])
1
2
eight_immortal = ['汉钟离', '张果老', '韩湘子', '铁拐李', '吕洞宾', '何仙姑', '蓝采和', '曹国舅']
print(eight_immortal[-8])
print(eight_immortal[-4])
print(eight_immortal[-1])
1
2
3
4

当我们想一次访问列表中的多个元素时,比如我们想访问铁拐李、吕洞宾、何仙姑时,就可以使用切片啦!

切片操作对列表同样是适用的,语法是 列表名[m:n],访问的元素从索引 m 开始到索引 n 结束,不包括 n。

当不指定 m 和 n 时,也就是列表名[:] 访问的是整个列表;

当只指定 m ,不指定 n 时,列表名[m:] 访问的是从索引 m 开始,一直到列表结束的元素;

当只指定 n ,不指定 m 时,列表名[:n]访问的是从索引 0 开始,一直到索引 n  的元素,不包括索引 n 对应的元素。

铁拐李在列表中的位置是 3,吕洞宾是 4,何仙姑是 5,因此访问他们三个的语句是 eight_immortal[3:6]

eight_immortal = ['汉钟离', '张果老', '韩湘子', '铁拐李', '吕洞宾', '何仙姑', '蓝采和', '曹国舅']
print(eight_immortal[3:6])
print(eight_immortal[2:])
print(eight_immortal[:5])
print(eight_immortal[:])
1
2
3
4
5

同样的还可以使用负数索引。

eight_immortal = ['汉钟离', '张果老', '韩湘子', '铁拐李', '吕洞宾', '何仙姑', '蓝采和', '曹国舅']
print(eight_immortal[-5:-2])
print(eight_immortal[-5:])
print(eight_immortal[:-2])
print(eight_immortal[:])
1
2
3
4
5

在进行切片操作时,还可以指定索引的步长。

我们首先一起了解下步长指的是什么?

大家小的时候有没有下过跳棋,我们可以往前跳一步,就是跳一个格子,步长即为 1;也可以跳两步,就是跳两个格子,步长就是 2,我们一起来看下 eight_immortal 这个列表各元素间的步长:

9a584c6c5662105eec6b3178d95a4f55

了解步长的含义之后,我们来看步长的表达。

列表名[m:n:步长] 步长在实际的编程中,是用数据表示的,1 表示 1 步,2 表示 2 步,步长也可以省略,省略时步长默认为 1。

我们一起来看下下方语句:

大家在运行前,先自己判断下运行结果:

eight_immortal = ['汉钟离', '张果老', '韩湘子', '铁拐李', '吕洞宾', '何仙姑', '蓝采和', '曹国舅']
print(eight_immortal[0:7:2])
1
2

打印的结果是:汉钟离、韩湘子、吕洞宾、蓝采和,这部分内容刚开始了解时,确实是有些容易混淆的,我们多练习几次就好了。

eight_immortal = ['汉钟离', '张果老', '韩湘子', '铁拐李', '吕洞宾', '何仙姑', '蓝采和', '曹国舅']
print(eight_immortal[-8:-1:2])
1
2

当步长为-1时,会是什么结果呢?

步长为 1,表示从前向后访问,步长为 -1,即表示反向访问,起点为汉钟离,反向访问1步,访问到曹国舅,继续反向访问 1 步,为蓝采和,我们运行下方语句,看下步长为 -1 的列表运行结果。

eight_immortal = ['汉钟离', '张果老', '韩湘子', '铁拐李', '吕洞宾', '何仙姑', '蓝采和', '曹国舅']
print(eight_immortal[::-1])
1
2

最终打印出的结果,我们看到实现了列表的翻转。

也就是说,我们可以通过将步长设置为 -1,来实现列表的翻转。

#5 列表可以嵌套

列表中的元素同样可以是一个列表。

my_list = ['a', ['bb', ['ccc', 'ddd'], 'ee', 'ff'], 'g', ['hh', 'ii'], 'j']
print(my_list)
1
2

我们看到在 my_list 这个列表中有 5 个元素,其中 3 个是字符型,2 个是列表,而['bb',['ccc','ddd'],'ee','ff'] 这个列表中又嵌套了一个列表,在判断列表中的嵌套时,我们主要是根据[]来进行判断:

19cebb9f2ce47d0b0737d1248cc77600

嵌套的列表共占元素的一个位置,具体位置信息我们一起来看图:

3acb62c4c07dec491d95290af09f7e7c

我们看到对于只嵌套一个的列表,访问其中某个元素时,索引的使用方法是列表名[嵌套列表的位置][所需访问的元素在嵌套列表的位置],比如,我们想访问hh,方法就是my_list[3][0],3 是嵌套列表在 my_list 中的位置,0 是 hh 在嵌套列表中的位置。

如果我们想访问 ddd,索引为 my_list[1][1][1]

我们一起看下下方语句,还是在运行前,我们先判断下结果哈!

my_list = ['a', ['bb', ['ccc', 'ddd'], 'ee', 'ff'], 'g', ['hh', 'ii'], 'j']
print(my_list[0])
print(my_list[1])
print(my_list[1][0])
print(my_list[1][1][0])
1
2
3
4
5

下面,我们一起来看下列表的最后一个特性:列表中的元素可以修改。

#6 列表元素可修改

#6.1 改变元素的值

#6.1.1 一次改变一个值

逍遥闲散的汉钟离,把手中的芭蕉扇甩开扔到大海里,那扇子大如蒲席,他醉眼惺忪地跳到迎波踏浪的扇子上,悠哉悠哉地向大海深处漂去。清婉动人的何仙姑步其后尘,将荷花往海里一放,顿时红光四射,花像磨盘,仙姑亭亭玉立于荷花中间,风姿迷人。众仙谁也不甘落后。吟诗行侠的吕洞宾、倒骑毛驴的张果老、隐迹修道的曹国舅、振靴踏歌的蓝采和、巧夺造化的韩湘子、借尸还魂的铁拐李纷纷将宝物扔入海中。瞬间,百舸争流,各显神通,逞雄镇海,悠然地遨游在万顷碧波之中。

我们现在想把列表中的’汉钟离’修改成’逍遥闲散’,把列表中的’何仙姑’修改成’清婉动人’,我们可以先使用索引定位到需要修改的元素位置,再通过赋值的方式将修改后的内容赋值给对应元素:

eight_immortal[0] = '逍遥闲散'

eight_immortal[5] = '清婉动人'

运行下方语句,我们一起看下修改效果:

eight_immortal = ['汉钟离', '张果老', '韩湘子', '铁拐李', '吕洞宾', '何仙姑', '蓝采和', '曹国舅']

eight_immortal[0] = '逍遥闲散'
eight_immortal[5] = '清婉动人'

print(eight_immortal)
1
2
3
4
5
6

我们看到打印出的结果是修改后的内容,大家把索引和赋值部分的知识点熟悉好,一次改变一个值的列表修改也就非常简单啦!

#6.1.2 一次改变多个值

现在我们想将’汉钟离’修改成’逍遥闲散’,’张果老’修改成’倒骑毛驴’,’韩湘子’修改成’巧夺造化’,

当然我们可以采用逐一修改的方式,但是代码规范中有一个要求就是代码的简洁程度,能同时修改的值尽量不多次修改,下面呢,我们就给大家介绍可以一次性修改多个值的方法:

我们观察到在 eight_immortal 列表中,’汉钟离’、’张果老’、’韩湘子’是可以通过切片的方式同时访问到的,因此我们先通过切片定位到这些元素的位置,再将修改后的值通过[]逐一赋值给他们。

eight_immortal = ['汉钟离', '张果老', '韩湘子', '铁拐李', '吕洞宾', '何仙姑', '蓝采和', '曹国舅']

eight_immortal[0:3] = ['逍遥闲散', '倒骑毛驴','巧夺造化']

eight_immortal = ['汉钟离', '张果老', '韩湘子', '铁拐李', '吕洞宾', '何仙姑', '蓝采和', '曹国舅']

eight_immortal[0:3] = ['逍遥闲散', '倒骑毛驴','巧夺造化']

print(eight_immortal)
1
2
3
4
5

我们也可以将列表中元素的值修改为整型,比如下方语句

eight_immortal = ['汉钟离', '张果老', '韩湘子', '铁拐李', '吕洞宾', '何仙姑', '蓝采和', '曹国舅']

eight_immortal[0:3] = [10, 20, 30]
eight_immortal[-5:-1] = [40, 50, 60, 70]

print(eight_immortal)
1
2
3
4
5
6

大家要打好每一步基础,如果学习过程中,发现哪部分的知识点掌握的不够熟悉,要重新回顾下相应内容哦!

#6.2 删除元素

现在呢,我们想把八仙中的张果老从列表中删除,只需要使用 del 就可以了

del 列表名[],铁拐李在列表中的位置为 eight_immortal[1],因此删除语句为  del eight_immortal[1]

eight_immortal = ['汉钟离', '张果老', '韩湘子', '铁拐李', '吕洞宾', '何仙姑', '蓝采和', '曹国舅']

del eight_immortal[1]
print(eight_immortal)
1
2
3
4

我们也可以使用 del 来进行多个元素的删除,del 列表名[m:n],我们运行下方语句:

eight_immortal = ['汉钟离', '张果老', '韩湘子', '铁拐李', '吕洞宾', '何仙姑', '蓝采和', '曹国舅']

del eight_immortal[0:3]
print(eight_immortal)
1
2
3
4

我们看到’汉钟离’、’张果老’、’韩湘子’从列表中删除了。

#6.3 使用 + 往列表中增加元素

八仙的传说起源很早,但人物有多种说法。如淮南八仙,所指西汉淮南王刘安著成《淮南子》的八公,淮南王好神仙丹药,后世传其为仙。五代时道士作画幅为蜀中八仙,所画人物有容成公、李耳、董仲舒、张道陵、严君平、李八百、范长生、尔朱先生。

现在我们想把容成公、李耳、董仲舒、张道陵、严君平、李八百、范长生、尔朱先生都包含在列表eight_immortal中,该怎么添加呢?

在 Python 中,我们使用+往列表中添加元素,添加的元素会自动的被添加到列表尾部:

列表名 += [元素1,元素2,元素3,...,元素n]

因此语句为:

eight_immortal = ['汉钟离', '张果老', '韩湘子', '铁拐李', '吕洞宾', '何仙姑', '蓝采和', '曹国舅']
print(eight_immortal)

eight_immortal += ['容成公', '李耳', '、董仲舒','张道陵','严君平','李八百','范长生','尔朱先生']
print(eight_immortal)
1
2
3
4
5

我们看到添加的内容在列表 eight_immortal 原有元素之后。

#6.4 改变列表的方法

#6.4.1 append()

除了使用+append() 也可以为列表添加元素,和+一样,也是在列表的结尾处添加元素,可以添加一个元素或列表。

我们看下方语句:

eight_immortal = ['汉钟离', '张果老', '韩湘子', '铁拐李']
print(eight_immortal)

eight_immortal.append('吕洞宾')
print(eight_immortal)

eight_immortal.append(['何仙姑', '蓝采和', '曹国舅'])
print(eight_immortal)
1
2
3
4
5
6
7
8

使用+append()都是在列表的结尾处添加元素,那如果是想在列表的开始处添加元素或者是在列表中的任意位置添加元素需要如何实现呢?

#6.4.2 insert()

在 Python 中,insert() 可以在指定位置插入一个元素或列表。

语法是:insert(n, 需要添加的元素/列表值),n 为需要插入元素或列表的指定位置

我们一起来看一个例子:

eight_immortal = ['汉钟离', '张果老', '韩湘子', '铁拐李']
print(eight_immortal)

eight_immortal.insert(3, '吕洞宾')
print(eight_immortal)

eight_immortal.insert(4, ['何仙姑', '蓝采和', '曹国舅'])
print(eight_immortal)
1
2
3
4
5
6
7
8

在列表的指定位置插入了相应的元素和列表。

#6.4.3 remove()

我们可以在列表中添加元素,也可以删除元素,我们使用 remove(元素值)  从列表中删除指定的元素,如果指定的元素在列表中不存在,则会报错。

比如:

eight_immortal = ['汉钟离', '张果老', '韩湘子', '铁拐李', '吕洞宾', '何仙姑', '蓝采和', '曹国舅']
print(eight_immortal)

eight_immortal.remove('汉钟离')
print(eight_immortal)

eight_immortal.remove('骆宾王')
1
2
3
4
5
6
7

#6.4.4 pop(index)

除了 remove(),我们还可以使用 pop(index) 来删除指定元素,index 为元素在列表中的位置。

pop(index) 语法规则为:列表名.pop(index),从列表中删除指定索引上的元素,如果不指定 index,默认删除最后一个元素。

eight_immortal = ['汉钟离', '张果老']
print(eight_immortal)

eight_immortal.pop()
print(eight_immortal)
1
2
3
4
5

我们看到 pop() 没有指定元素位置,则列表中最后一个元素’张果老’被删除了。

我们再一起看下指定元素位置的情况,运行下方语句:

eight_immortal = ['汉钟离', '张果老', '韩湘子', '铁拐李', '吕洞宾', '何仙姑', '蓝采和', '曹国舅']
print(eight_immortal)

eight_immortal.pop(1)
print(eight_immortal)
1
2
3
4
5

我们看到列表中删除了指定元素’张果老’。

都是删除元素,pop()和 remove() 主要有两点不同:

  1. pop()传入的参数为索引值,而不是具体的元素值。
  2. pop()的返回值为删除的元素。

我们可以通过一个变量,来看下 pop() 的返回值

eight_immortal = ['汉钟离', '张果老', '韩湘子', '铁拐李', '吕洞宾', '何仙姑', '蓝采和', '曹国舅']
name = eight_immortal.pop(1)
print(name)
1
2
3

我们看到打印出的结果是张果老,也就是 pop(1) 返回的值。

#7 总结

3acb62c4c07dec491d95290af09f7e7c

#8 练习题

seven_sage = ['山涛', '阮籍', '刘伶', '嵇康', '向秀', '阮咸', '王戎'],通过列表索引的方法打印出 '山涛'

  1. seven_sage = ['山涛', '阮籍', '刘伶', '嵇康', '向秀', '阮咸', '王戎'],通过列表切片的方法打印出 '山涛', '阮籍', '刘伶', '嵇康'
  2. seven_sage = ['山涛', '阮籍', '刘伶', '嵇康', '向秀', '阮咸', '王戎'],删除元素 '阮籍'

 

第六章循环

在上一关中,我们讲述了如何创建一个列表以及如何访问列表中的元素。

3acb62c4c07dec491d95290af09f7e7c-1

在这一关中,我们会讲述如何使用少量的几行代码来遍历列表,而不用关心列表的长度。

循环使得我们能够对列表中的每个元素执行相同的操作,这样对于任意长度的列表我们都可以很高效地对其进行处理。

远古的时候,大地出现了严重的旱灾。炎热烤焦了森林,烘干了大地,晒干了禾苗草木。原来,帝俊与羲和生了 10 个孩子都是太阳,他们住在东方海外,海水中有棵大树叫扶桑。10 个太阳睡在枝条的底下,轮流跑出来在天空执勤,照耀大地。但有时,他们一齐出来给人类带来了灾难。为了拯救人类,后羿张弓搭箭,向那 9 个太阳射去。只见天空出现爆裂的火球,坠下一只只三足乌。最后,天上只留下一个太阳。

现在需要我们使用循环语句来帮助后羿判断,什么情况下需要后羿保持射箭状态。

我们先来看for循环

#for 循环

for 循环用于迭代序列(即列表、元组、字典、集合或字符串等)。这与其他编程语言中的 for 关键字不太相似,而是更像其他面向对象编程语言中的迭代器方法。

通过使用 for 循环,我们可以为列表、元组、集合中的每个元素执行一系列的操作。

#1.1 for 循环语法

74ed4459263946f5b14433cd0a74760d

#1.2 for 循环流程图

2c5e06806750ed4020640d269c4e879a

#1.3 实例

我们一起来看一个数字的实例:依次打印出 1~20

# 打印出1-20
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]

for var in numbers:
    print(var)
1
2
3
4
5

我们也可以在这个基础上进行进一步的数字计算,比如对 1 到 20 的数字进行求和:

# 对 1 到 20 的数字求和
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]

count = 0
for var in numbers:
    count += var

print("count = ", count)
1
2
3
4
5
6
7
8

我们了解了 for 循环的使用方法之后,我们一起来帮助后羿判断射箭的动作什么时候可以停下来吧?

天空中有 10 个太阳,后羿的任务是要射掉其中的九只,留下一只在天上工作来保障地球的正常运转。也就是说,当天空中太阳数量为 2~10 时,后羿需要保持射箭动作。我们可以将天空中太阳的数量用一个列表sun_in_sky 表示,当太阳数量为2~10时,后羿需要继续射箭!语句如下,我们点击运行:

# 天空中的太阳数量在2-10时,保持射箭!
sun_in_sky = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

for i in sun_in_sky:
    if i > 1:
        print("继续射箭 ")
1
2
3
4
5
6

#while 循环

我们也可以使用 while 循环来帮助后羿做判断,我们一起先来了解下 while 的语法规则:

while 循环:只要条件满足,就会一直执行一组语句。Python 中,while 表示的信息是当…时候,也就是说当 while 循环的条件满足时,会一直执行满足条件的语句。

#2.1 while 循环语法

b7cac9e918602fa4c218baaba88af416

在一次循环的过程中,首先会判断 condition 是否为 True。如果为 True,则执行循环体语句。

一次循环结束之后,会继续判断 condition 是否为 True,如果为 True,则继续执行循环体语句;上述过程会一直持续下去,直到 condition 为 False

#2.2 while 循环流程图

300ea2ff7efdff5c8dd150036b475614

#2.3 实例

和 for 循环一样,我们一起来看下使用 while 循环打印出:1~20。

# 打印1-20
i = 0
while i < 20:
    i += 1
    print(i)
1
2
3
4
5

我们继续来看一个复杂一些的例子,对 20 以内的正整数求和:

# 对 20 以内的正整数求和
count = 0
n = 20
i = 1
while i <= 20:
    count += i
    i += 1

print("count = ", count)
1
2
3
4
5
6
7
8
9

了解了 while 循环的语法规则之后,我们一起来看下如何用 while 循环来帮助后羿判断是否需要继续射箭呢?我们来回顾下后羿射箭的条件:当天空中太阳数量为 2~10 时,后羿需要保持射箭动作!

# 当天空中太阳数量为2-10时,大羿需要保持射箭动作!
sun_in_sky = 10
while sun_in_sky > 1:
    sun_in_sky -= 1
    print("继续射箭")
1
2
3
4
5

#break 和 continue

一般情况下,循环语句会重复执行循环体语句,直到循环条件不满足。但是,在有些情况下,我们需要提前结束本轮循环或者直接结束整个循环。这时候便要用到 break 和 continue 语句。

break 和 continue 语句的使用,通常是与 if 条件语句配合的,当满足 if 条件语句的时候,结束整个循环或者结束本轮循环。

我们一起先来看下 break 语句:

#3.1 break

如果想提前结束整个循环,可以使用 break 语句。

我们一起来看下方例子:对 1 到 20 的数字求和(和为 210),当和大于 100 时,停止求和,退出整个循环。

我们运行下方语句:

#3.1.1 将 break 用于 for 循环

# 对 1 到 20 的数字求和,当和大于 100 时,便停止求和
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]

count = 0
for var in numbers:
    count += var
    if count >= 100:
        break

print("count = ", count)
1
2
3
4
5
6
7
8
9
10

我们看到打印出的结果是 105,我们提取出其中的 for 语句:

8542b5e4236e6f551600e3c878e5b780

3.1.2 将 break 用于 while 循环

我们一起再来看下 while 循环中break 的使用:

# 对 20 以内的正整数求和,当和大于 100 时,停止求和
count = 0
n = 20
i = 1
while i <= 20:
    count += i
    i += 1
    if count >= 100:
        break

print("count = ", count)
1
2
3
4
5
6
7
8
9
10
11

我们看到打印的结果还是 105,当 count 值为 105 时,满足条件判断语句 if count >= 100: 执行break,退出整个循环。

在这里还是提醒大家,注意代码规范哟,注意各个语句的缩进,if 语句块是包含在 while 语句块中的,因此if 语句前面有 4 个空白字符,break 语句是在 if 语句下的,因此 break 语句相较于 if 语句前方又有四个空白字符,还有冒号及所有代码都是英文状态下的,这些细节千万不要忽略哈。

#3.2 continue

break 语句是结束整个循环,如果想提前结束本轮循环,可以使用 continue 语句。

#3.2.1 将 continue 用于 for 循环

我们先一起来看下continue 在 for 循环的应用,大家点击运行。

# 对 20 以内的偶数求和
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]

count = 0
for var in numbers:
    # 奇数,除以2的余数不为0,也就是不能被2整除
    if var % 2 != 0:
        # 当数字为奇数时,退出本次循环
        continue
    count += var

print("count = ", count)
1
2
3
4
5
6
7
8
9
10
11
12

结果实现了对 20 以内偶数的求和。我们来看这部分的 for 循环语句:

6db83bee94554082977e6100c4a22b51

continue 是退出本次循环,当数字为奇数时,则退出本次循环,不执行循环体内的命令;当数字为偶数时,执行循环体内的命令,完成求和。如果在上述语句中,continue 的位置是 break,打印的结果就是0,因为第一次循环 1 就是奇数,不能对 2 整除,直接跳出了整个循环,没有执行 count 变量的求和运算,结果还是count 的原始赋值 0。通过这个例子,希望大家可以分辨清 continue 和 break 循环的语法规则 ,能够灵活运用哦!

#3.2.2 将 continue 用于 while 循环

我们继续来看下continue 在于 while 循环中的应用:

# 对 20 以内的偶数求和
count = 0
n = 20
i = 0
while i < 20:
    i += 1
    if i % 2 != 0:
        continue
    count += i

print("count = ", count)
1
2
3
4
5
6
7
8
9
10
11

语法规则是一样的哦,当i是奇数时,退出本次循环,不执行 count += i求和语句,当i为偶数时,则执行求和语句,实现对 20 以内的偶数求和!

#4 总结

我们一起来看下本关总结:

feea3e48d780ea692cdf64164cbf0531

#5 练习题

#5.1 使用 for 配合 continue 求解 20 以内的奇数的和。

#5.2 使用 while 配合 continue 求解 20 以内的奇数的和。

 

第七章字典

今天要开启第七关啦,在第七关开始之前,我们来回顾下第六关的内容:

feea3e48d780ea692cdf64164cbf0531-1

第六关中,我们介绍循环语句 for 和 while,以及中断循环语句 break 和 continue

下面,我们正式开启本关的闯关啦!本关我们将为大家介绍字典:

{'姓名':'张三','年龄':18} 就是一个字典,字典是一系列键值对的集合,姓名:张三 便是一个键值对,其中键为姓名,值为 张三。创建字典时,只需要将键值对用花括号{} 括起来,每个键值对的键和值之间用冒号 : 分隔,每个键值对之间用逗号 , 分隔。

(注意:冒号和逗号均为英文状态下的逗号和冒号)。

3a01f1096b6642cd26f4b9b2f4ff3767

我们首先来看字典的创建语法:

#1 字典创建语法

d = {<key>: <value>,<key>: <value>,...<key>: <value>}

用大括号 {} 将键值对括起来,键值对的键和值之间用冒号 : 分隔,键值对之间用逗号 , 分隔。

#2 创建字典

现在我们一起看下字典的创建,哪吒闹海的神话故事大家一定非常熟悉,哪吒自幼喜欢习武,有一天,他同小朋友在海边嘻戏,正好碰上巡海夜叉,与东海龙王三太子出来肆虏百姓,残害儿童。小哪吒见此恶徒,义愤填膺,挺身而出,打死夜叉与三太子敖丙又抽了它的龙筋。东海龙王得知此讯后勃然大怒,降罪于哪吒的父亲,随即兴风作浪,口吐洪水淹没陈塘关。小哪吒不愿牵连父母,于是自己剖腹、剜肠、剔骨,还筋肉于双亲,仙师太乙真人借着荷叶莲花之力,为其脱胎换骨,化作莲花化身的哪吒。后来大闹东海,砸了龙宫,捉了龙王,为民除害。

这里呢,我们拿王者荣耀中哪吒这个英雄的各项属性值来创建一个字典:

c03d9409dd854dc20483c3d9d4421cf6

属性数据字典:

ne_zha = {'英雄名字': '哪吒', '最大生命': 7268, '生命成长': 270.4, '初始生命': 3483, '最大法力': 1808, '法力成长': 97, '初始法力': 450, '最高物攻': 320, '物攻成长': 11.5, '初始物攻': 159, '最大物防': 408, '物防成长': 22.07, '初始物防': 99}
print(ne_zha)
print(type(ne_zha))
1
2
3

我们看到打印出了哪吒这个英雄的各项属性,数据类型返回值是字典。

需要注意的是,在创建字典时,字典中的键值不能重复,重复会报错。

#3 访问字典

字典创建完成之后,我们想要访问字典中的英雄名字、最大生命、生命成长的值,该如何访问呢?

访问字典中某个键值对的值:字典名[键名],只需要将键值对的键名放到方括号 [] 中就可以啦。

我们运行下方语句。

ne_zha = {'英雄名字': '哪吒', '最大生命': 7268, '生命成长': 270.4, '初始生命': 3483, '最大法力': 1808, '法力成长': 97, '初始法力': 450,'最高物攻': 320, '物攻成长': 11.5, '初始物攻': 159, '最大物防': 408, '物防成长': 22.07, '初始物防': 99}

print(ne_zha['英雄名字'])
print(ne_zha['最大生命'])
print(ne_zha['生命成长'])
1
2
3
4
5

我们看到结果显示了英雄名字、最大生命和生命成长这三个键对应的值。

除了使用上述方式进行访问外,我们还可以使用 get() 方法进行访问,语法规则是字典名.get(键名)

我们运行下方语句:

ne_zha = {'英雄名字': '哪吒', '最大生命': 7268, '生命成长': 270.4, '初始生命': 3483, '最大法力': 1808, '法力成长': 97, '初始法力': 450, '最高物攻': 320, '物攻成长': 11.5, '初始物攻': 159, '最大物防': 408, '物防成长': 22.07, '初始物防': 99}

print(ne_zha.get('英雄名字'))
print(ne_zha.get('最大生命'))
print(ne_zha.get('生命成长'))
1
2
3
4
5

除了上述两种方法,我们还可以通过遍历的方式(一般通过for循环来实现遍历哦)来访问字典中的键值对。

下面代码逐个打印字典中的所有键名。

ne_zha = {'英雄名字': '哪吒', '最大生命': 7268, '生命成长': 270.4, '初始生命': 3483, '最大法力': 1808, '法力成长': 97, '初始法力': 450, '最高物攻': 320, '物攻成长': 11.5, '初始物攻': 159, '最大物防': 408, '物防成长': 22.07, '初始物防': 99}

for key in ne_zha:
    print(key)
1
2
3
4

上述语句是打印键名,打印值的话,使用的是下方语句:

key 表示键名,根据刚刚我们介绍的访问键值的方法, ne_zha[key] 便表示键值。

#逐个打印字典中的所有值
ne_zha = {'英雄名字': '哪吒', '最大生命': 7268, '生命成长': 270.4, '初始生命': 3483, '最大法力': 1808, '法力成长': 97, '初始法力': 450, '最高物攻': 320, '物攻成长': 11.5, '初始物攻': 159, '最大物防': 408, '物防成长': 22.07, '初始物防': 99}

for key in ne_zha:
    print(ne_zha[key])
1
2
3
4
5

另外,还可以使用 values() 函数返回字典的值,语法规则是字典名.values(),运行下方语句:

ne_zha = {'英雄名字': '哪吒', '最大生命': 7268, '生命成长': 270.4, '初始生命': 3483, '最大法力': 1808, '法力成长': 97, '初始法力': 450, '最高物攻': 320, '物攻成长': 11.5, '初始物攻': 159, '最大物防': 408, '物防成长': 22.07, '初始物防': 99}

for value in ne_zha.values():
    print(value)
1
2
3
4

还可以使用 items() 函数遍历键和值,语法规则是字典名.items(),运行下方语句:

(key 表示键名,value 表示键值)

ne_zha = {'英雄名字': '哪吒', '最大生命': 7268, '生命成长': 270.4, '初始生命': 3483, '最大法力': 1808, '法力成长': 97, '初始法力': 450, '最高物攻': 320, '物攻成长': 11.5, '初始物攻': 159, '最大物防': 408, '物防成长': 22.07, '初始物防': 99}

for key, value in ne_zha.items():
    print("key = ", key, ", value = ", value)
1
2
3
4

#4 修改字典

和列表一样,我们可以对创建好的字典进行相应的修改。

我们首先来看在字典中添加项目。

#4.1 添加项目

我们之前在变量和列表中都介绍了索引,现在又是索引发挥作用的时刻了,我们可以通过使用新的索引键并为其赋值,来为字典添加新的项目。

我们使用索引将哪吒的“最大每5秒回血”这个属性添加到 ne_zha 这个字典中,具体语句如下:

ne_zha = {'英雄名字': '哪吒', '最大生命': 7268, '生命成长': 270.4, '初始生命': 3483, '最大法力': 1808, '法力成长': 97, '初始法力': 450, '最高物攻': 320, '物攻成长': 11.5, '初始物攻': 159, '最大物防': 408, '物防成长': 22.07, '初始物防': 99}

ne_zha['最大每5秒回血'] = 98
print(ne_zha)
1
2
3
4

我们看到哪吒的“最大每5秒回血”添加到了ne_zha 这个字典的结尾处。

#4.2 删除项目

除了可以往字典中添加项目,我们也可以从字典中删除项目。我们可以通过多种方式删除字典中的项目,我们逐一介绍给大家:

#4.2.1 pop() 方法

pop() 方法删除具有指定键名的项,语法规则为字典名.pop(键名)。键名如果是字符串,记得加英文状态下的引号哟!我们运行下方语句:

ne_zha = {'英雄名字': '哪吒', '最大生命': 7268, '生命成长': 270.4, '初始生命': 3483, '最大法力': 1808, '法力成长': 97, '初始法力': 450, '最高物攻': 320, '物攻成长': 11.5, '初始物攻': 159, '最大物防': 408, '物防成长': 22.07, '初始物防': 99}

ne_zha.pop('英雄名字')
print(ne_zha)
1
2
3
4

#4.2.2 popitem()

popitem() 方法删除最后插入的项目(在 3.7 之前的版本中,删除随机项目),语法规则为字典名.popitem()

运行下方语句:

ne_zha = {'英雄名字': '哪吒', '最大生命': 7268, '生命成长': 270.4, '初始生命': 3483, '最大法力': 1808, '法力成长': 97, '初始法力': 450, '最高物攻': 320, '物攻成长': 11.5, '初始物攻': 159, '最大物防': 408, '物防成长': 22.07, '初始物防': 99}

print(ne_zha)
ne_zha.popitem()
print(ne_zha)
1
2
3
4
5

我们看到执行 popitem() 语句之后,字典中最后位置的 '初始物防': 99 被删除了。

#4.2.3 del

我们也可以使用 del 关键字删除具有指定键名的项目,语法规则为 del 字典名[键名],我们运行下方语句:

ne_zha = {'英雄名字': '哪吒', '最大生命': 7268, '生命成长': 270.4, '初始生命': 3483, '最大法力': 1808, '法力成长': 97, '初始法力': 450, '最高物攻': 320, '物攻成长': 11.5, '初始物攻': 159, '最大物防': 408, '物防成长': 22.07, '初始物防': 99}

del ne_zha['最大生命']
print(ne_zha)
1
2
3
4

我们看到字典 ne_zha 中的 '最大生命': 7268 被删除了。

del 关键字也可以完全删除字典,语法规则为:del 字典名

ne_zha = {'英雄名字': '哪吒', '最大生命': 7268, '生命成长': 270.4, '初始生命': 3483, '最大法力': 1808, '法力成长': 97, '初始法力': 450, '最高物攻': 320, '物攻成长': 11.5, '初始物攻': 159, '最大物防': 408, '物防成长': 22.07, '初始物防': 99}

del ne_zha
print(ne_zha)  # 会报错,因为删除之后 ne_zha 不再存在。
1
2
3
4

#4.2.4 clear()

除了删除字典,我们也可以清空字典,有没有非常羡慕程序呢,有时候我们也想清空下自己,却发现实施起来太难太难!

clear() 函数清空字典,语法规则为:字典名.clear(),运行下方语句:

ne_zha = {'英雄名字': '哪吒', '最大生命': 7268, '生命成长': 270.4, '初始生命': 3483, '最大法力': 1808, '法力成长': 97, '初始法力': 450, '最高物攻': 320, '物攻成长': 11.5, '初始物攻': 159, '最大物防': 408, '物防成长': 22.07, '初始物防': 99}

ne_zha.clear()
print(ne_zha)
1
2
3
4

#5 复制字典

在变量和列表中,我们可以通过 name2 = name1 的语句来将变量或者是列表的内容进行复制,但对于字典来说,是不能通过键入 dict2 = dict1 来复制字典。因为,dict2 只是对 dict1 的引用,而 dict1 中的更改也将自动在 dict2 中进行。有一些方法可以进行复制,一种方法是使用内建的字典方法 copy(),语法规则是 字典名.copy(),通过 ne_zha_copy = ne_zha.copy() 语句来实现列表 ne_zha 的复制,我们运行下方语句:

ne_zha = {'英雄名字': '哪吒', '最大生命': 7268, '生命成长': 270.4, '初始生命': 3483, '最大法力': 1808, '法力成长': 97, '初始法力': 450, '最高物攻': 320, '物攻成长': 11.5, '初始物攻': 159, '最大物防': 408, '物防成长': 22.07, '初始物防': 99}

ne_zha_copy = ne_zha.copy()
print(ne_zha_copy)
1
2
3
4

制作副本的另一种方法是使用内建方法 dict(),语法规则是 dict(字典名),通过ne_zha_copy = dict(ne_zha) 语句来实现对字典 ne_zha 的复制,运行下方语句:

ne_zha = {'英雄名字': '哪吒', '最大生命': 7268, '生命成长': 270.4, '初始生命': 3483, '最大法力': 1808, '法力成长': 97, '初始法力': 450, '最高物攻': 320, '物攻成长': 11.5, '初始物攻': 159, '最大物防': 408, '物防成长': 22.07, '初始物防': 99}

ne_zha_copy = dict(ne_zha)
print(ne_zha_copy)
1
2
3
4

#6 使用 dict() 创建字典

我们也可以使用 dict() 构造函数创建新的字典,语法规则为:字典名 = dict(键名=键值, 键名=键值,..., 键名=键值)

# 注意:1.关键字不是字符串字面量;2.使用了等号而不是冒号来赋值。
ne_zha = dict(英雄名字='哪吒', 最大生命=7268, 生命成长=270.4, 初始生命=3483, 最大法力=1808, 法力成长=97, 初始法力=450, 最高物攻=320, 物攻成长=11.5, 初始物攻=159, 最大物防=408, 物防成长=22.07, 初始物防=99)

print(ne_zha)
1
2
3
4

#7 总结

下面我们一起来看下本关总结:

fc91b93281f35e7961d3f531617b1277

#8 练习题

我们通过两个题目来验证下大家对于字典的掌握效果哦!

#8.1 向字典 ne_zha = {'英雄': '哪吒', '最大生命': 7268, '生命成长': 270.4, '初始生命': 3483, '最大法力': 1808, '法力成长': 97, '初始法力': 450, '最高物攻': 320, '物攻成长': 11.5, '初始物攻': 159, '最大物防': 408, '物防成长': 22.07, '初始物防': 99}中添加项目 {'每5秒回血成长': 3.214}

#8.2 从字典 ne_zha = {'英雄': '哪吒', '最大生命': 7268, '生命成长': 270.4, '初始生命': 3483, '最大法力': 1808, '法力成长': 97, '初始法力': 450, '最高物攻': 320, '物攻成长': 11.5, '初始物攻': 159, '最大物防': 408, '物防成长': 22.07, '初始物防': 99}中删除项目 {'初始物攻': 159}

第八章元组

我们首先来回顾下上一关的内容,上一关我们介绍了字典:

fc91b93281f35e7961d3f531617b1277-1

今天,我们一起进入到元组的学习。

元组和列表很像,区别在于元组创建完成后便不能被修改。创建元组很简单,只需要将用逗号分隔的元素放到  () 中,(元素1,元素2,元素3,...,元素n),如果元素为字符串,别忘记添加引号哟!

我们首先一起来看下元组的创建。

#1 创建元组

龙,是中国的“图腾”,在中国古代神话传说中,龙生有九子,九子不成龙,各有所好。比喻同胞兄弟品质、爱好各不相同。龙生的九子分别是:长子囚牛、次子睚眦(yá zì)、三子嘲风、四子蒲牢、五子狻猊(Suān ní)、六子霸下、七子狴犴(bì àn)、八子负屃(fù xì)、九子螭吻(chī wěn)。

我们创建一个元组,包含这九子,语句如下:

loong_son = ('囚牛', '睚眦', '嘲风', '蒲牢', '狻猊', '霸下', '狴犴', '负屃', '螭吻')

print(loong_son)
1
2
3

如果需要创建一个仅包含一个元素的元组,必须在该元素后面添加一个逗号,否则,Python 无法将变量识别为元组。比如,我们只想创建一个仅仅包含长子囚牛的元组,语句如下:

loong_son1 = ('囚牛') # 不是元组
loong_son2 = ('囚牛',)

print(type(loong_son1))
print(type(loong_son2))
1
2
3
4
5

友情提示:type() 是获取数据类型的方法哦!

#2 访问元组

现在呢,我们想要访问元组 loong_son 中的囚牛、嘲风、螭吻,该如何访问呢?

大家可以回想下在之前列表、字典的介绍中,我们是如何访问其中的元素的。

我们可以使用索引操作符 [] 访问元组的元素,我们可以从左到右正索引,也可以从右到左负索引。我们先来看下正索引的语句:

#2.1 正索引

loong_son = ('囚牛', '睚眦', '嘲风', '蒲牢', '狻猊', '霸下', '狴犴', '负屃', '螭吻')

print(loong_son[0])
print(loong_son[2])
print(loong_son[8])
1
2
3
4
5

我们成功访问了囚牛、嘲风、螭吻。

#2.2 负索引

负索引表示从末尾开始,-1 表示最后一个元素,-2 表示倒数第二个元素,依此类推。

loong_son = ('囚牛', '睚眦', '嘲风', '蒲牢', '狻猊', '霸下', '狴犴', '负屃', '螭吻')

print(loong_son[-1])
print(loong_son[-7])
print(loong_son[-9])
1
2
3
4
5

成功访问了囚牛、嘲风、螭吻。

索引部分的内容和之前介绍的一样,正索引是从左到右,用 0 表示第一个元素;负索引是从右到左,用 -1 表示右边第一个元素,大家一定要记清楚哟!

#2.3 切片

现在我们想访问龙的前三个孩子,即囚牛、睚眦、嘲风,怎么操作呢?

当然,我们可以通过索引的方式一个一个访问出来,但是这样操作的效率非常低!

我们在学习前面知识的时候提到过,通过切片可以一次访问多个元素,对于访问元组中的多个元素,还是采用切片的方式:

loong_son = ('囚牛', '睚眦', '嘲风', '蒲牢', '狻猊', '霸下', '狴犴', '负屃', '螭吻')
print(loong_son[0:3])
1
2

关于切片的语法,大家可以通过下方语句回顾下,这里我们就不过多介绍啦!

loong_son = ('囚牛', '睚眦', '嘲风', '蒲牢', '狻猊', '霸下', '狴犴', '负屃', '螭吻')

print(loong_son[1:])
print(loong_son[:3])
print(loong_son[:])
print(loong_son[-3:-1])
print(loong_son[-3:])
print(loong_son[:-1])
1
2
3
4
5
6
7
8

#2.4 遍历元组

我们也可以使用 for 循环遍历元组元素,运行下方语句。

loong_son = ('囚牛', '睚眦', '嘲风', '蒲牢', '狻猊', '霸下', '狴犴', '负屃', '螭吻')

for elem in loong_son:
    print(elem)
1
2
3
4

通过 for 循环,我们完成了元组 loong_son 中元素的遍历。

#3 元组修改

我们在介绍元组时提到了元组的一个特征是:元组在创建完成后便不能被修改!因此任何关于修改元组的操作都会报错,比如添加新元素到元组中,或者是删除元组中的某些元素,我们逐一来看下添加和删除两种情况:

#3.1 添加元素

元组一旦创建,就无法向其添加元素,元组是不可改变的。

loong_son = ('囚牛', '睚眦', '嘲风', '蒲牢', '狻猊', '霸下', '狴犴', '负屃', '螭吻')

loong_son[10] = '龙' # 会报错,元组不可改变
1
2
3

#3.2 删除元素

元组是不可改变的,因此无法从中删除元素,但可以删除整个元组。

loong_son = ('囚牛', '睚眦', '嘲风', '蒲牢', '狻猊', '霸下', '狴犴', '负屃', '螭吻')

del loong_son
print(loong_son) # 会报错,因为删除之后,loong_son 不再存在
1
2
3
4

#4 合并元组

元组不能被修改,但是两个元组是可以合并成一个新的元组的,在 Python 中,使用 + 运算符可以连接两个或多个元组,语句如下:

loong_son1 = ('囚牛', '睚眦', '嘲风', '蒲牢', '狻猊')
loong_son2 = ('霸下', '狴犴', '负屃', '螭吻')

loong_son = loong_son1 + loong_son2
print(loong_son)
1
2
3
4
5

我们看到通过 + 运算符,元组 loong_son1 和元组 loong_son2 形成了一个新的元组 loong_son

#5 总结

下面我们一起来回顾下本关内容:

3da06f91dfe6a8bf8667ca55050e2665

#6 练习题

创建一个包含 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' 这个 12 个元素的元组,并尝试对元组进行修改,看看会报什么错。

第九章集合

我们先来一起复习下上一关元组的内容:

3da06f91dfe6a8bf8667ca55050e2665-1

今天我们来学习集合。

集合是无序元素的集合,集合中的元素不可重复,并且创建完成后,其中的元素不可更改。但是整个集合是可以更改的,我们可以向其增加元素,也可以从中删除元素。也就是说,我们无法修改集合中的元素,但是我们可以对整个集合进行添加或者是删除等更改的操作。

集合的创建非常简单,只需要将以逗号分隔的元素放在花括号 {} 中,{元素1,元素2,元素3,...,元素n}

#1 集合创建

不知道大家是否有个武侠梦呢,我从小就喜欢看武侠小说,以及根据小说改编的各种电视剧,最爱的就是气度翩翩的赵敏,黎姿版的赵敏真的是一眸一笑深入人心…啧啧啧,有些跑偏,还不小心暴露了年纪,我们还是回到课程中来。

现在呢,我们来创建一个名为 novels 的集合,集合中的元素为武侠小说的名称,让我们在集合的世界里畅游武侠江湖!

novels = {'飞狐外传', '雪山飞狐', '连城诀', '天龙八部', '射雕英雄传', '白马啸西风', '鹿鼎记', '笑傲江湖', '书剑恩仇录', '神雕侠侣', '侠客行', '倚天屠龙记', '碧血剑', '鸳鸯刀'}

print(novels)
1
2
3

集合中的元素不可重复,如果有重复元素,重复的元素将被忽略。

novels = {'飞狐外传', '飞狐外传', '雪山飞狐', '连城诀', '天龙八部', '射雕英雄传', '白马啸西风', '鹿鼎记', '笑傲江湖', '书剑恩仇录', '神雕侠侣', '侠客行', '倚天屠龙记', '碧血剑', '鸳鸯刀'}

print(novels)
1
2
3

我们看到集合中有两个元素 '飞狐外传',但是打印的集合中,只显示一个飞狐外传,集合中的第二个元素 '飞狐外传' 被认定为是重复元素,被忽略,没有显示。

#2 集合访问

我们在介绍集合时,提到了集合中的元素是无序的!(列表、元组都是有序的哦)

元素的顺序主要应用在索引中,集合中的元素是无序的,也就无法应用索引进行访问了。

那么访问集合中的元素可以通过哪些方式呢?

我们可以通过 for 循环来遍历集合的元素,另外,还可以使用 in 关键字来判断集合中是否存在某个元素。

我们首先来看通过 for 循环遍历集合的元素。

#2.1 for 循环

novels = {'飞狐外传', '雪山飞狐', '连城诀', '天龙八部', '射雕英雄传', '白马啸西风', '鹿鼎记', '笑傲江湖', '书剑恩仇录', '神雕侠侣', '侠客行', '倚天屠龙记', '碧血剑', '鸳鸯刀'}

for novel in novels:
    print(novel)
1
2
3
4

#2.2 in

使用 in 关键字来判断集合中是否存在某个元素,如果元素在集合内,返回 True,如果元素不在集合内,返回 False,运行下方语句:

novels = {'飞狐外传', '雪山飞狐', '连城诀', '天龙八部', '射雕英雄传', '白马啸西风', '鹿鼎记', '笑傲江湖', '书剑恩仇录', '神雕侠侣', '侠客行', '倚天屠龙记', '碧血剑', '鸳鸯刀'}

print('鸳鸯刀' in novels)
print('越女剑' in novels)
1
2
3
4

鸳鸯刀在集合中,因此返回 True;越女剑不在集合中,返回 False

#3 集合修改

我们也可以对整个集合进行一些修改。

#3.1 add() and update()

add() 和 update() 都可用于向集合添加元素。

语法规则为:集合名.add(元素名)集合名.update({元素1,元素2,...,元素n})

我们看到 add() 和 update() 的一个区别是 add() 添加的是一个元素;update() 添加的是集合或者是列表,添加的是多个元素,我们一起来运行下方语句:

novels = {'飞狐外传', '雪山飞狐', '连城诀', '天龙八部', '射雕英雄传', '白马啸西风', '鹿鼎记'}

novels.add('笑傲江湖')
print(novels)
novels.add('书剑恩仇录')
print(novels)
novels.add('神雕侠侣')
print(novels)

novels.update({'侠客行', '倚天屠龙记'})  # update 的参数为集合
print(novels)
novels.update(['碧血剑', '鸳鸯刀'])
print(novels)  # update 的参数为列表
1
2
3
4
5
6
7
8
9
10
11
12
13

我们看到执行 add() 和 update() 的语句后,在集合结尾处添加了相应的元素。

#3.2 discard() and remove()

除了可以对整个集合添加元素,我们还可以删除集合中的元素。

discard() 和 remove() 用于从集合中删除元素。

语法规则为:集合名.discard()集合名.remove()。这两个函数的区别在于,从集合中删除一个不存在的元素时,discard() 不会执行任何操作,而 remove() 会抛出一个异常。

#3.2.1 删除存在的元素

我们首先看一下删除存在的元素,discard() 和 remove()的使用是一样的,结果也是一样的,运行下方语句:

novels = {'飞狐外传', '雪山飞狐', '连城诀', '天龙八部', '射雕英雄传', '白马啸西风', '鹿鼎记', '笑傲江湖', '书剑恩仇录', '神雕侠侣', '侠客行', '倚天屠龙记', '碧血剑', '鸳鸯刀'}

novels.discard('飞狐外传')
print(novels)
novels.remove('雪山飞狐')
print(novels)
1
2
3
4
5
6

#3.2.2 删除不存在的元素

对于删除不存在的元素,discard() 不会执行任何操作,而 remove() 会抛出一个异常,运行下方语句:

novels = {'飞狐外传', '雪山飞狐', '连城诀', '天龙八部', '射雕英雄传', '白马啸西风', '鹿鼎记', '笑傲江湖', '书剑恩仇录', '神雕侠侣', '侠客行', '倚天屠龙记', '碧血剑', '鸳鸯刀'}

novels.discard('越女剑')  # 不会执行任何操作
print(novels)
1
2
3
4
novels = {'飞狐外传', '雪山飞狐', '连城诀', '天龙八部', '射雕英雄传', '白马啸西风', '鹿鼎记', '笑傲江湖', '书剑恩仇录', '神雕侠侣', '侠客行', '倚天屠龙记', '碧血剑', '鸳鸯刀'}

novels.remove('越女剑')  # 会抛出异常
print(novels)
1
2
3
4

我们看到 discard() 不会执行任何操作,而 remove() 会抛出一个异常。

大家在删除集合中的元素时,要灵活掌握这些方法哦!

#4 集合操作

我们在数学中,也学习到了集合的相关概念,在数学中,我们可以对集合进行一系列的操作,比如并集、交集和差集。Python 中的集合,我们也可以做相应的操作,实现 Python 集合的并集、交集和差集。

我们先一起来看下 Python 中集合的并集:

#4.1 并集

在数学中,关于并集的定义是:给定两个集合A,B,把他们所有的元素合并在一起组成的集合,叫做集合 A 与集合 B 的并集,记作 A∪B,读作 A 并 B。

Python 中的并集也是一个含义,将集合 A 和集合 B 的所有元素合并在一起,就组成了集合 A 和集合 B 的并集。Python 中,实现集合并集可以使用 union() 和 | 操作符。

7e9cb31599cd19a0ad96c90e732a9b5c

#4.1.1 union()

我们先来看下使用 union() 实现集合的并集,语法规则为:集合1.union(集合2),运行下方语句:

novels_1 = {'飞狐外传', '雪山飞狐', '连城诀', '天龙八部', '射雕英雄传', '白马啸西风', '鹿鼎记', '笑傲江湖'}
novels_2 = {'鹿鼎记', '笑傲江湖', '书剑恩仇录', '神雕侠侣', '侠客行', '倚天屠龙记', '碧血剑', '鸳鸯刀'}

print(novels_1.union(novels_2))
print(novels_2.union(novels_1))
1
2
3
4
5

我们看到,通过 union() 实现了集合 novels_1 和集合 novels_2 的并集。

#4.1.2 |

也可以使用 | 对两个集合进行并集的运算,语法规则为 集合1|集合2,运行下方语句:

novels_1 = {'飞狐外传', '雪山飞狐', '连城诀', '天龙八部', '射雕英雄传', '白马啸西风', '鹿鼎记', '笑傲江湖'}
novels_2 = {'鹿鼎记', '笑傲江湖', '书剑恩仇录', '神雕侠侣', '侠客行', '倚天屠龙记', '碧血剑', '鸳鸯刀'}

print(novels_1 | novels_2)
1
2
3
4

#4.2 交集

我们继续一起来看交集:

A,B 是两个集合,由所有属于集合 A 且属于集合 B 的元素所组成的集合,叫做集合 A 与集合 B 的交集(intersection),记作 A∩B。我们使用 intersection() 和 & 实现不同集合间的交集。

b51f95da5103a2a646320d0071b80c50

#4.2.1 intersection()

可以实现集合 A 和集合 B 的交集运算,语法规则是 集合1.intersection(集合2),运行下方语句 :

novels_1 = {'飞狐外传', '雪山飞狐', '连城诀', '天龙八部', '射雕英雄传', '白马啸西风', '鹿鼎记', '笑傲江湖'}
novels_2 = {'鹿鼎记', '笑傲江湖', '书剑恩仇录', '神雕侠侣', '侠客行', '倚天屠龙记', '碧血剑', '鸳鸯刀'}

print(novels_1.intersection(novels_2))
print(novels_2.intersection(novels_1))
1
2
3
4
5

#4.2.2 &

& 也可以实现集合 A 和集合 B 的交集运算,语法规则是 集合1 & 集合2,运行下方语句:

novels_1 = {'飞狐外传', '雪山飞狐', '连城诀', '天龙八部', '射雕英雄传', '白马啸西风', '鹿鼎记', '笑傲江湖'}
novels_2 = {'鹿鼎记', '笑傲江湖', '书剑恩仇录', '神雕侠侣', '侠客行', '倚天屠龙记', '碧血剑', '鸳鸯刀'}

print(novels_1 & novels_2)
1
2
3
4

我们看到打印出了两个集合间的交集。

#4.3 差集

集合 A 和集合 B 中,只属于其中一个集合,不属于另一个集合的元素。比如属于集合 A 不属于集合 B 的元素集合,或者是属于集合 B 不属于集合 A 的元素集合。

4e5781caeb65db432c80a4f9e0a74cb2

#4.3.1 difference()

我们可以使用 difference() 来实现差集的运算,语法规则为集合1.difference(集合2):即实现属于集合 1 不属于集合 2 的差集,我们一起运行下方语句:

novels_1 = {'飞狐外传', '雪山飞狐', '连城诀', '天龙八部', '射雕英雄传', '白马啸西风', '鹿鼎记', '笑傲江湖'}
novels_2 = {'鹿鼎记', '笑傲江湖', '书剑恩仇录', '神雕侠侣', '侠客行', '倚天屠龙记', '碧血剑', '鸳鸯刀'}

print(novels_1.difference(novels_2))
print(novels_2.difference(novels_1))
1
2
3
4
5

当集合 novels_1 在 difference() 之前时,打印的是属于集合 novels_1 不属于集合 novels_2 的元素集合,集合 novels_2 在 difference() 之前时,打印的是属于集合 novels_2 不属于集合 novels_1 的元素集合。

#4.3.2 -

我们可以使用-来实现差集的运算,语法规则为 集合1-集合2:即实现属于集合 1 不属于集合 2 的差集,我们一起运行下方语句:

novels_1 = {'飞狐外传', '雪山飞狐', '连城诀', '天龙八部', '射雕英雄传', '白马啸西风', '鹿鼎记', '笑傲江湖'}
novels_2 = {'鹿鼎记', '笑傲江湖', '书剑恩仇录', '神雕侠侣', '侠客行', '倚天屠龙记', '碧血剑', '鸳鸯刀'}

print(novels_1 - novels_2)
print(novels_2 - novels_1)
1
2
3
4
5

#4.4 对称差集

对称差集就是属于集合 A,不属于集合 B 的以及属于集合 B 不属于集合 A 的元素集合,就是集合 A 与集合 B 的并集减去集合 A 与集合 B 的交集。

e378b4066c3f3db9754631e18b5ee50c

#4.4.1 symmetric_difference()

我们可以使用 symmetric_difference() 来实现对称差集的运算,语法规则是:集合1.symmetric_difference(集合2),一起来运行下方语句:

novels_1 = {'飞狐外传', '雪山飞狐', '连城诀', '天龙八部', '射雕英雄传', '白马啸西风', '鹿鼎记', '笑傲江湖'}
novels_2 = {'鹿鼎记', '笑傲江湖', '书剑恩仇录', '神雕侠侣', '侠客行', '倚天屠龙记', '碧血剑', '鸳鸯刀'}

print(novels_1.symmetric_difference(novels_2))
print(novels_2.symmetric_difference(novels_1))
1
2
3
4
5

#4.4.2 ^

我们可以使用 ^ 来实现对称差集的运算,语法规则是:集合1^集合2,一起来运行下方语句:

novels_1 = {'飞狐外传', '雪山飞狐', '连城诀', '天龙八部', '射雕英雄传', '白马啸西风', '鹿鼎记', '笑傲江湖'}
novels_2 = {'鹿鼎记', '笑傲江湖', '书剑恩仇录', '神雕侠侣', '侠客行', '倚天屠龙记', '碧血剑', '鸳鸯刀'}

print(novels_1 ^ novels_2)
print(novels_2 ^ novels_1)
1
2
3
4
5

#5 总结

今天的介绍就到这里了,我们一起看下本关总结:

4793d75291ab9161eeba3a619dbbb091

#6 练习题

求集合 novels_1 = {'飞狐外传', '雪山飞狐', '连城诀', '天龙八部', '射雕英雄传', '白马啸西风', '鹿鼎记', '笑傲江湖', '书剑恩仇录'}novels_2 = {'白马啸西风', '鹿鼎记', '笑傲江湖', '书剑恩仇录', '神雕侠侣', '侠客行', '倚天屠龙记', '碧血剑', '鸳鸯刀'}的并集,交集,差集和对称差集。

第十章函数

今天我们开始函数的学习,在函数内容开始之前,我们先来复习上一关集合的内容:

4793d75291ab9161eeba3a619dbbb091-1

下面,我们正式开始函数的学习:

在 Python 中,函数是一组相关的语句,这些语句完成一个特定的任务。为了完成任务,我们只要调用相应的函数即可。在前面的章节中,对内容进行打印的 print() 就是一个函数,它的作用是将内容打印到屏幕上。

#1 为什么需要函数?

假设你编写了可以完成某个特定任务的一组代码,记为 block A。随着开发的推进,你发现 block A 在很多地方都能用到。这时候,你该怎么办?一种简单粗暴的解决方案便是将 block A 复制粘贴到需要的地方。过了一段时间之后,你发现需要对 block A 进行改动,改动的原因可能是发现了 bug,也可能是想优化 block A。这时候,如果 block A 的副本散落在程序的各个角落,你需要对每一处的 block A 进行修改。这种修改方式不仅易于出错,而且容易引入难以发现的 bug。另外,对于后期的程序维护来说简直就是噩梦。

一种比较好的解决方案是定义一个函数来完成指定的任务。函数的定义完成后,在程序的任何地方如果需要完成相同的任务,只需要调用函数即可。如果以后的某个时间点,需要优化完成任务的方法,只需要在一处进行更改,也就是定义函数的地方。函数的定义修改之后,其他调用函数的地方会随之更改。效率大大提升,而且不容易出错。

下面,我们一起来认识下函数,首先呢,我们先来学习下如何定义函数:

#2 函数的定义

#2.1 语法

689d602e3b6cd41d68c3fa77563025a2

  1. 关键字 def 标识函数头的开始。
  2. function_name 为函数名,命名规则和变量相同。
  3. parameters 以逗号分隔的参数列表,用来接收传递给函数的值,参数列表是可选的。虽然参数列表是可选的,但是函数名后面的括号是必须的。
  4. : 标识函数头的结束。
  5. statement(s) 组成函数体的一条或多条语句,这些语句必须是相同的缩进(一般是缩进 4 个空格)。

一般我们看到关键字 def 开始的语句,就表示这是一个函数。我们来看一个实例:

#2.2 实例

我们借用大禹治水的故事来学习函数。

很久很久以前,洪水经常泛滥。大水淹没了田地,冲毁了房屋,毒蛇猛兽到处伤害百姓和牲畜,人们的生活痛苦极了。

洪水给百姓带来了无数的灾难,必须治好它。当时,一个名叫鲧的人领着大家治水。他只知道筑坝挡水,九年过去了,洪水仍然没有消退。他的儿子禹继续治水。

禹离开了家乡,一去就是十三年。这十三年里,他到处奔走,曾经三次路过自己家门口。可是他认为治水要紧,一次也没有走进家门看一看。

禹吸取了鲧治水失败的教训,采取疏导的办法治水。他和千千万万的人一起,疏通了很多河道,让洪水通过河道,最后流到大海里去。洪水终于退了,毒蛇猛兽被驱赶走了,人们把家搬了回来。大家在被水淹过的土地上耕种,农业生产渐渐恢复了,百姓重新过上了安居乐业的生活。

我们现在定义一个函数 greet(),函数语句为打印大禹治水。

函数定义语句如下:

def greet():
    print("大禹治水")
1
2

我们现在只是定义函数,运行上述语句是没有任何结果显示的,如果想打印出函数定义的语句内容 print("大禹治水"),则需要调用函数。也就是说,关于函数的使用,包含两个步骤,第一步是定义函数,第二步是在函数定义好之后,调用函数,我们一起继续来看下函数是如何被调用的?

#3 函数的调用

我们先来看下函数调用的语法规则:

#3.1 语法

function_name(parameters)
1

parameters 为传递给函数的值,是可选的。即便不需要传递值给函数,函数名后的括号也是必须的。

#3.2 实例

我们再来看下定义的函数 greet(),按照函数调用的语法,只需要在定义函数语句之后,使用调用函数语句    greet() 即可完成函数的调用,运行下方语句,看下运行效果:

def greet():
    print("大禹治水")

greet()
1
2
3
4

我们看到结果显示出了大禹治水这四个字,表示我们完成了对函数 greet() 的调用。

我们在函数定义和函数调用的介绍中,都提到了函数的参数,下面,我们就一起来了解下,如何进行函数参数的传递。

#4 传递参数

虽然不带参数的函数也可以完成某些特定任务,但是,大多数时候,我们需要给函数传递值,这样的话,每次调用函数的行为都会因为传递的值不同而变得不同。

参数的传递分为不同的情况,我们现在就为大家逐一介绍各种情况:

#4.1 位置参数

我们先来看下位置参数,所谓的位置参数,就是表示参数的位置对于函数的结果是有影响的,同样的参数值,在不同的位置,会有不一样的结果表达,我们一起看下方实例:

因为古人大禹治水的成功,才使得子孙后辈进入到了美好的生活中。

小明妈妈让小明去买 6 个香蕉,共花费了 5.74,我们一起来看下,如果用函数实现上述信息的输出,该如何实现呢?我们运行下方语句:

def cal(qty, item,price):
    print(f'{qty} {item} cost ${price:.2f}')

cal(6, 'bananas', 5.74)
1
2
3
4

我们首先定义了一个函数 cal(),函数 cal() 中有三个参数,分别是参数 qty、参数 item 和参数price,当调用函数 cal() 时,传递三个参数的值 6,'bananas',5.74 给函数,最终运行结果为 6 bananas cost $5.74

d643759361ca021c4cc4dc940679312f

小贴士: print(f'{qty} {item} cost ${price:.2f}') 语句中的 f' 表示格式化输出,格式化 {}中的内容,不在 {}内的语句照常展示输出!其中的 {:.2f} 表示保留两位小数,如果是 {:.0f} 则不保留小数位。

现在小明妈妈让小明去买苹果,小明买好后回来和妈妈说,2 个苹果花费 8.18,还是调用上方函数,只需要在调用函数时,修改参数值即可:

def cal(qty, item,price):
    print(f'{qty} {item} cost ${price:.2f}')

cal(2, 'apples', 8.18)
1
2
3
4

在上面的例子中,参数 qty 的值为 2item 的值为 'apples'price 的值为 8.182,'apples',8.18 的顺序和个数必须要和 qty,item,price 相同。如果顺序不同,将会得到错误的结果(程序没有错误,只不过表达出的含义和我们最终想要实现的不一致,即得到错误的结果)。

def cal(qty, item, price):
    print(f'{qty} {item} cost ${price:.2f}')


cal('apples', 8.18, 2)  # 得到错误的结果
1
2
3
4
5

如果个数不同,调用函数的时候会报错。

def cal(qty, item, price):
    print(f'{qty} {item} cost ${price:.2f}')


cal(2, 'apples')  # 参数过少
1
2
3
4
5
def cal(qty, item, price):
    print(f'{qty} {item} cost ${price:.2f}')


cal(2, 'apples', 8.18, 'bananas')  # 参数过多
1
2
3
4
5

#4.2 关键字参数

在传递值的时候,还可以带上参数的名字,具体形式为 keyword = value,这里的 keyword 必须匹配上一个函数定义中的参数名,也就是说是 参数名1=值1参数名2=值2参数名3=值3 这种形式。

我们一起运行下方语句:

def cal(qty, item, price):
    print(f'{qty} {item} cost ${price:.2f}')


cal(qty=6, item='bananas', price=5.74)
1
2
3
4
5

我们看到语句和之前的对比,区别在于调用函数传递参数值时,参数的名字和值进行了对应。

这种情况下,如果指定的 keyword 在函数定义中没有出现,将会报错。

def cal(qty, item, price):
    print(f'{qty} {item} cost ${price:.2f}')


cal(qty=6, item='bananas', cost=5.74)  # 会报错
1
2
3
4
5

在指定了参数名之后,值的顺序和函数定义中的参数顺序可以不用保持一致。

def cal(qty, item, price):
    print(f'{qty} {item} cost ${price:.2f}')


cal(item='bananas', price=5.74, qty=6)
1
2
3
4
5

虽然顺序可以不用保持一致,但是值的个数还需要和参数的个数保持相同。不同的话会报错。

def cal(qty, item, price):
    print(f'{qty} {item} cost ${price:.2f}')


cal(qty=6, item='bananas')  # 会报错
1
2
3
4
5
def cal(qty, item, price):
    print(f'{qty} {item} cost ${price:.2f}')


cal(qty=6, item='bananas', price=5.74, cost=6)  #会报错
1
2
3
4
5

#4.3 默认参数

在定义函数时,我们还可以指定参数的默认值。

指定默认值之后,在调用函数时如果没有指定某个参数的值,就用参数的默认值。

我们分别来看下面几种不同情况:

  1. 调用时,每个参数都给出了值,这时候便用调用时指定的值。
def cal(qty=6, item='bananas', price=5.74):
    print(f'{qty} {item} cost ${price:.2f}')


cal(4, 'apples', 2.24)
1
2
3
4
5
  1. 调用时,只给出了部分参数的值,这时候没有给出值的参数,使用的就是其默认值。
def cal(qty=6, item='bananas', price=5.74):
    print(f'{qty} {item} cost ${price:.2f}')


cal(4, 'apples')
1
2
3
4
5

上述语句没有指定参数 price 的值,则使用参数 price 的默认值 5.74

def cal(qty=6, item='bananas', price=5.74):
    print(f'{qty} {item} cost ${price:.2f}')


cal(4)
1
2
3
4
5

上述语句没有指定参数 item、参数 price 的值,则使用参数 item 的默认值 bananas、参数 price 默认值 5.74

  1. 调用时,也可以不给出参数的值,这时候全部使用默认的值。
def cal(qty=6, item='bananas', price=5.74):
    print(f'{qty} {item} cost ${price:.2f}')


cal()
1
2
3
4
5
  1. 调用时,也可以指定参数名。
def cal(qty=6, item='bananas', price=5.74):
    print(f'{qty} {item} cost ${price:.2f}')


cal(item='kumquats', qty=9)
1
2
3
4
5
def cal(qty=6, item='bananas', price=5.74):
    print(f'{qty} {item} cost ${price:.2f}')


cal(price=2.29)
1
2
3
4
5

#return 语句

Python 函数中的 return 语句有两个作用:

  1. 立即结束本函数的执行,将程序的执行控制权交还给调用者。
  2. 返回数据给调用者。

我们一起来看下方实例:

def f(x):
    if x < 0:
        return
    if x > 100:
        return
    print(x)


f(-3)
f(105)
f(64)
1
2
3
4
5
6
7
8
9
10
11

当调用函数 f(-3) 时,传递参数值 -3,回到函数 f(x) 中,符合语句 x < 0,执行 return 语句,立即返回;执行调用函数 f(105) 语句,符合语句 x > 100,执行 return 语句,立即返回;执行调用函数f(64) 语句,64 既不 < 0,也不 > 100,执行 print(x) 语句,打印出 64。

f(-3) 和 f(105) 由于条件成立,会立即返回,而不会执行后面的 print() 语句,f(64) 条件不成立,执行 print() 语句,打印出 64。

我们再来看一个实例,求任意数字的绝对值:

def absolute_value(num):
    if num >= 0:
        return num
    else:
        return -num


print(absolute_value(2))
print(absolute_value(-4))
1
2
3
4
5
6
7
8
9

我们首先定义一个求绝对值的函数 absolute_value(num),参数为 num,函数语句块为当参数大于等于 0时,返回参数值 num,当参数小于 0 时,返回参数值 -num

第二步为打印调用函数 absolute_value(num) 值,当参数值为 2 时,absolute_value(2) 调用返回 2;当参数值为 -4 时,absolute_value(-4) 调用返回参数值 –4,即为 4。

#6 总结

下面,我们一起来总结下函数的知识:

b6768355d84743f9be890cadbfb8fc05

#7 练习题

  1. 编写一个函数返回两个数中的较大值。
  2. 编写一个函数计算圆的面积。

 

第十一章类和对象

上一关我们为大家介绍了函数,我们一起来回顾下上一关的内容:

b6768355d84743f9be890cadbfb8fc05-1

今天呢,我们将为大家介绍类和对象,类和对象是面向对象编程的核心概念。

我们一起来通过百鸟朝凤的故事认识 Python 中的类和对象:

一天,伏羲巡视到西山桐林,只见金、木、风、火、土五行之精,纷纷飘落在梧桐树上。顿时,仙乐飘飘,香风习习。又见瑞气千条,霞光万道。天空彩屏开处,祥云托着两只美丽的大鸟,翩翩降落在那棵梧桐树上,其余诸鸟纷纷飞集在各处树上,朝着两只美丽的大鸟齐鸣。伏羲见到如此奇异现象,忙召来辅佐他的木神句芒问个究竟。句芒笑着对伏羲道:“这两只最大的鸟,就是凤凰呀!”

故事中,当凤凰出现的时候,所有鸟都朝着凤凰齐鸣,说明了凤凰在鸟类当中的地位。而凤凰之所以能够吸引到鸟,而不是其他动物,也是因为凤凰和其余鸟,同属于鸟这个大类里面,应了“物以类聚”这句话。我们生活中,会将具有一些共性特征的生物或者是物体划分为一类,比如鸟类、鱼类、厨房用品、办公用品等等。Python 中的类,和我们生活的“物以类聚”类似,都是包含了这一类别内都具备的一些特征。Python 中的类是用来描述具有相同的属性和方法的对象的集合,它定义了该集合中每个对象所共有的属性和方法。类是抽象的模板,比如说鸟类,我们在提到鸟类的时候,并不知道具体是哪一种鸟;对象是对类进行具象的实例化,比如说凤凰、鹦鹉、麻雀等,他们都是鸟的一种,提到凤凰、鹦鹉、麻雀的时候,我们会在脑海中勾勒出具体的形象;而在类中,我们也可以对凤凰、鹦鹉、麻雀这些鸟进行一些属性的定义,比如羽毛颜色、尺寸大小等等。下面呢,我们分别为大家介绍 Python 中的类与对象,首先我们来看,类的创建:

#1 类

#1.1 创建类

我们一起来看下类是如何创建的:

bdf3a0aa4cd2f9381d06aff3ed63c809

类的定义以关键字 class 开头,后面紧跟类名和冒号,下面跟着是类的主体部分,代码以缩进标识。

我们一起来看下方语句:

#创建类Bird
class Bird:
    #对象初始化语句
    def __init__(self, n, c, s):
        self.name = n
        self.color = c
        self.size = s
    
    #定义方法get_description,参数为self,自动传入
    def get_description(self):
        description = f'{self.name} {self.color} {self.size} '
        print(description)
1
2
3
4
5
6
7
8
9
10
11
12

我们创建了一个类 Bird,并定义了类 Bird 的两种方法(类中的函数称作方法) __init__( )get_description( ),这两个方法是所有属于类 Bird 的对象共有的方法,下面我们一起看下 Python 中初始化属性的方法 __init__( )

#1.2 __init__() 方法

类中的函数称作方法,__init__() 是一个特殊的方法,每当我们实例化一个对象时,这个方法都会自动执行。方法名的开头为两个下划线,结尾同样为两个下划线,这种命名的习惯主要是为了区分 Python 默认的方法名和我们自己定义的方法名。

def __init__(self, n, c, s): 语句中,参数 self 表示对象自身,代表实例化对象的引用。参数n, c, s则表示对象的属性,在我们创建的类 Bird 中就是表示,每一种鸟的具象化特征,比如鹦鹉、绿色、中等大小,因此 __init__() 方法的作用是为对象的属性赋值。

__init__() 的参数规则如下图: 7ee477ae903cc7cb1d3588c99cf5a417

参数 self 是必须的,并且要位于其他参数的前面。在方法的定义中,之所以要必须包含 self 参数,是因为当实例化对象时,会自动调用 __init__() 方法,并且自动传入参数 self。每个方法都可以包含一个会自动传入的参数 self,这个参数是实例化对象的引用。这样方法便可以访问对象的属性和方法。在实例化对象时,由于 self 参数自动传入的,所以只需要传入其他参数的值。

我们再来一起看下 __init__() 函数体中的语句:

def __init__(self, n, c, s):
    #对象初始化语句
        self.name = n
        self.color = c
        self.size = s
1
2
3
4
5

__init__() 函数体中,赋值号左边的参数带有 self 前缀,带有 self 前缀的变量对于类中的每个方法来说都是可用的,而且也可以通过实例化的对象来访问这些变量。self.name = n 将参数 n 赋值给 namename 便是实例化出来的对象的属性;self.color = c 将参数 c 赋值给 colorcolor便是实例化出来的对象的属性;self.size = s 将参数 s 赋值给 sizesize便是实例化出来的对象的属性。

我们继续来看类 Bird 中定义的方法 get_description() 语句:

def get_description(self):
    #定义方法get_description,参数为self,自动传入
        description = f'{self.name} {self.color} {self.size} '
        print(description)
1
2
3
4

这个方法由于不需要传入额外的信息,所以只要传入 self 参数,函数中定义了变量 description 和打印description 的语句,当调用 get_description() 方法时,执行打印语句。

我们继续一起来看对象:

#2 对象

类是用来描述具有相同的属性和方法的对象的集合,它定义了该集合中每个对象所共有的属性和方法。类是抽象的,对象是对类进行具象的实例化。我们从刚刚的例子中,也了解到了,类是鸟类,对象是具体的某一种鸟,比如凤凰、麻雀、鹦鹉等等,下面我们就一起来看下如何通过 Python 语句来实现对象的实例化。

#2.1 实例化对象

我们先来看下方语句:

#创建类Bird
class Bird:

    #对象初始化语句
    def __init__(self, n, c, s):
        self.name = n
        self.color = c
        self.size = s

     #定义方法get_description,参数为self,自动传入
    def get_description(self):
        description = f'{self.name} {self.color} {self.size} '
        print(description)

#实例化对象my_bird,为my_bird赋予属性'鹦鹉', '绿色', '中等大小'
my_bird = Bird('鹦鹉', '绿色', '中等大小')
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

在语句中,我们添加了一句 my_bird = Bird('鹦鹉', '绿色', '中等大小') 会实例化类 Bird 的一个对象 my_bird,在实例化的过程中,会调用 __init__() 方法,将值'鹦鹉'传递给参数 n,值'绿色'传递给参数 c,值'中等大小'传递给参数 s

运行上述语句,我们看并没有结果的输出,因为只完成了类的定义,以及其中一个对象的实例化,并没有去调用类中定义的方法,也没有访问对象的属性。

下面就看一下对象的属性访问。

#2.2 访问属性

访问属性的语法为:对象名.属性名

我们看下方语句:

class Bird:

    def __init__(self, n, c, s):
        self.name = n
        self.color = c
        self.size = s

    def get_description(self):
        description = f'{self.name} {self.color} {self.size} '
        print(description)


my_bird = Bird('鹦鹉', '绿色', '中等大小')
print(f"My bird's name is {my_bird.name}")
print(f"My bird's color is {my_bird.color}")
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

在上面的语句中,我们通过 my_bird.name 和 my_bird.color 访问对象 my_bird 的属性 name 和 color。我们继续来看如何实现方法的访问。

#2.3 访问方法

访问方法的语法规则和访问属性是类似的,都是用 . 符号来实现:对象名.方法名

我们来看下方语句:

class Bird:
    def __init__(self, n, c, s):
        self.name = n
        self.color = c
        self.size = s

    def get_description(self):
        description = f'{self.name} {self.color} {self.size} '
        print(description)


my_bird = Bird('鹦鹉', '绿色', '中等大小')
my_bird.get_description()
1
2
3
4
5
6
7
8
9
10
11
12
13

我们看到通过访问方法语句 my_bird.get_description(),成功执行方法 get_description() 中的打印语句。

#2.4 实例化多个对象

我们还可以同时实例化多个对象:

class Bird:
    def __init__(self, n, c, s):
        self.name = n
        self.color = c
        self.size = s

    def get_description(self):
        description = f'{self.name} {self.color} {self.size} '
        print(description)


my_bird = Bird('鹦鹉', '绿色', '中等大小')
your_bird = Bird('麻雀', '灰色', '小小一只')
print(f"My bird's name is {my_bird.name}")
my_bird.get_description()
print(f"Your bird's name is {your_bird.name}")
your_bird.get_description()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

我们实例化了两个对象 my_bird 和 your_bird。在实际应用中,可以用同样的方法实例化多个对象哟!

#2.5 为属性设置默认值

我们也可以为属性设置默认值,一起看下方语句:

class Bird:
    def __init__(self, n, c, s):
        self.name = n
        self.color = c
        self.size = s
         #设置属性age的默认值为1
        self.age = 1
       

    def get_description(self):
        description = f'{self.name} {self.color} {self.size} '
        print(description)

    #定义获取属性age的方法
    def get_age(self):
        print(f"This bird is {self.age} ")


my_bird = Bird('鹦鹉', '绿色', '中等大小')
print(f"My bird's name is {my_bird.name}")
my_bird.get_description()
my_bird.get_age()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

我们在上述代码中添加了一个属性 age,并且将默认值设置成 1。并且添加一个方法 get_age() 用于获取属性 age 的值。

#2.6 直接改变属性的值

我们也可以直接修改属性值,语句为:对象名.属性名 = 值,我们一起看下方语句:

class Bird:
    def __init__(self, n, c, s):
        self.name = n
        self.color = c
        self.size = s
        self.age = 1

    def get_description(self):
        description = f'{self.name} {self.color} {self.size} '
        print(description)

    def get_age(self):
        print(f"This bird is {self.age} ")


my_bird = Bird('鹦鹉', '绿色', '中等大小')
my_bird.age = 3
my_bird.get_age()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

#2.7 通过方法改变属性的值

我们也可以通过方法来改变属性的值:

class Bird:
    def __init__(self, n, c, s):
        self.name = n
        self.color = c
        self.size = s
        self.age = 1

    def get_description(self):
        description = f'{self.name} {self.color} {self.size} '
        print(description)

    def get_age(self):
        print(f"This bird is {self.age} ")

    def update_age(self, a):
        self.age = a


my_bird = Bird('鹦鹉', '绿色', '中等大小')
my_bird.update_age(5)
my_bird.get_age()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

在上述语句中,我们定义了一个改变属性值的方法 update_age(),通过调用 update_age() 来改变属性的值。

#3 继承

在创建类时,不必每次都从零开始,假设我们想要创建的新类和已经创建过的类之间有一些共同的属性和方法,我们就可以从某个现有的类继承,新类称为子类,被继承的类称为父类。继承时,子类会获取父类的所有属性和方法,并且子类还可以定义自己的属性和方法。

子类的语法规则是:class 新类名(父类名),比如 class Penguin(Bird) 就表示一个子类,父类为 Bird

#3.1 子类的 __init__() 方法

在实例化子类的对象时,首先要为父类中的属性赋值,对父类属性的赋值可以使用父类的 __init__() 方法。

class Bird:
    def __init__(self, n, c, s):
        self.name = n
        self.color = c
        self.size = s
        self.age = 1

    def get_description(self):
        description = f'{self.name} {self.color} {self.size} '
        print(description)

    def get_age(self):
        print(f"This bird is {self.age} ")

    def update_age(self, a):
        self.age = a


class Penguin(Bird):
    def __init__(self, n, c, s):
        super().__init__(n, c, s)


my_bird = Penguin('企鹅', '黑白', '大')
my_bird.get_description()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

在上面的例子中,定义了一个新类 Penguin,新类继承自 Bird。在子类  Penguin 的 __init__() 方法中调用父类 Bird 的 __init__() 方法对父类中的属性进行赋值。语句中的 super() 函数是用于调用父类的一个方法。

#3.2 定义子类的属性和方法

我们也可以在子类中定义属性和方法,语法规则和在类中定义属性和方法的规则一致,我们看下方语句:

class Bird:
    def __init__(self, n, c, s):
        self.name = n
        self.color = c
        self.size = s
        self.age = 1

    def get_description(self):
        description = f'{self.name} {self.color} {self.size} '
        print(description)

    def get_age(self):
        print(f"This bird is {self.age} ")

    def update_age(self, a):
        self.age = a


class Penguin(Bird):
    def __init__(self, n, c, s):
        super().__init__(n, c, s)
        self.swimming_distance = 100

    def get_swimming_distance(self):
        print(f"企鹅可以游 {self.swimming_distance} 米.")


my_bird = Penguin('企鹅', '黑白', '大')
my_bird.get_description()
my_bird.get_swimming_distance()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

为子类添加了属性 swimming_distance 和方法 get_swimming_distance(),通过访问属性和方法打印出相应的结果。

#4 总结

138cbab3668be033f46f31e377267d6a

#5 练习题

定义一个表示鱼的类,并定义它的继承类海鱼。

 

第十二章模块和包

上一关,我们介绍了类和对象:

a800f6f568928016b138052b1eaac35b

这一关,我们将为大家介绍模块和包:

在开发大型软件时,随着代码写的越来越多,如果将所有的代码都放在一个文件里,势必为以后的维护带来很大的困难。正如仓颉造字一样,仓颉是黄帝的史官,用祖传结绳记事的老办法记载史实。时间一长,那些大大小小,奇形怪状的绳结都记了些什么,连他自己也没法辨认了。于是,仓颉开始想新的办法,用什么方式可以帮助大家分辨清不同的事物,在仓颉的努力下,他创造了文字,解决了这个问题。而在 Python 中,为了编写易于维护的代码,我们会将代码拆分放到不同的文件里,这样每个文件包含的代码相对就会减少。在 Python 中,一个 .py 文件称为一个模块(Module)。

模块化能够带来很多好处:

  1. 简化问题求解

将所有代码放在一个文件中时,我们需要考虑的是整个问题的求解,代码实现的复杂度大大增加。将代码拆分放在多个文件中时,每个文件只需要对子问题进行求解,代码实现的复杂度大大降低。

  1. 提高代码可维护性

由于解决不同子问题的代码放在了不同的文件中,代码之间的依赖性小,其中一个文件的修改对其他文件产生影响的几率大大降低。维护人员可以对其中一个文件的代码进行修改,而不必熟悉其他文件中的代码。由于每个文件专注于解决一个子问题,文件之间的并行开发成为可能。

  1. 提高代码可重用性

一个模块编写完成后,可以被其他地方引用。我们在编写程序的时候,也可以引用其他模块,包括 Python 内置的模块和来自第三方的模块。这样就不需要重复造轮子。大大提高了代码的复用性和开发效率。

  1. 减少代码冲突

模块提供了一个独立的命名空间,独立命名空间的好处是可以避免函数名和变量名冲突。相同名字的函数和变量可以放在不同的模块中。因此,我们自己在编写模块时,不必考虑名字会与其他模块冲突。但是也要注意,尽量不要与内置函数名字冲突。

了解了模块是什么之后,我们一起来看下如何创建模块?

#1 模块的创建

模块的创建非常简单,一个 .py 文件便是一个模块(Module)。将下面的代码保存在 utils.py 文件中,这个操作是非常简单的,只需要我们创建一个文件名为 utils 的 py 文件,然后将代码复制到 utils 的 py 文件中就完成了一个模块的创建。

# utils.py模块
def max_num(a, b):
    if a >= b:
        return a
    else:
        return b


def min_num(a, b):
    if a > b:
        return b
    else:
        return a
1
2
3
4
5
6
7
8
9
10
11
12
13

这样我们便创建了一个名为 utils 的模块,在这个模块中,定义了两个函数: max_nummin_num ,两个函数分别为求两个数中的大数和小数。

#2 模块的导入

#2.1 import <module_name>

模块创建完成后,可以使用 import 关键字来导入模块,例如:

import utils
1

我们看到通过 import 模块名 的方式完成了模块导入。

执行上述指令后,Python 首先会从自己内置模块中查找是否含有该模块的定义,若未查询到会从 sys.path 对应的模块路径查询是否含有对应模块的定义,如果搜索完成,仍然没有对应的模块时,则抛出 import 的异常。

也就是说当执行 import utils 这条指令时,Python 会从以下路径中搜索模块 utils.py 。

  1. 在当前目录下搜索该模块。
  2. 在环境变量 PYTHONPATH 指定的路径列表中依次搜索。
  3. 在 Python 安装路径的 lib 库中搜索。

上述路径可以通过变量 sys.path 获得,该变量位于模块 sys 中。sys.path是 Python 的一个系统变量,是 Python 搜索模块的路径列表。其获取的方法如下:

import sys

print(sys.path)
1
2
3

为了让创建的模块能够被找到,需要将模块放到上述路径中的一个,因为 Python 只会在这些路径中去查找模块,如果没有将模块创建在这些路径中,则找不到对应的模块,也就没办法应用模块中的对象和方法了。

现在呢,我们想要去调用模块 utils 中的 max_num 和 min_num 方法,第一步为导入模块 utils,第二步为调用模块 utils 中的两个方法,具体语句如下:

#导入模块utils
import utils

print(utils.max_num(4, 5))
print(utils.min_num(4, 5))
1
2
3
4
5

我们看到为了调用模块中的函数 max_num 和 min_num,需要在函数名前面添加 utils. 前缀。如果不添加 utils. 前缀 ,则会报错。

#2.2 from <module_name> import <name(s)>

下面,我们一起来看模块导入的另一种方法,直接导入模块中的对象,语句为:from 模块名 import 方法名,我们一起看下方实例:

from utils import max_num, min_num

print(max_num(4, 5))
print(min_num(4, 5))
1
2
3
4

使用这种方式导入时,调用 max_num 和 min_num 函数便不需要添加前缀 utils.

有时候,为了方便,会使用 from <module_name> import * 来导入模块中的所有对象。

from utils import *

print(max_num(4, 5))
print(min_num(4, 5))
1
2
3
4

#2.3 from <module_name> import  as <alt_name>

大家在成长过程中,都会有一些别名,仓颉也有,仓颉又被称为“造字圣人”,“造字圣人”就是仓颉的别名。

Python 中模块内的对象和方法也可以有自己的别名,实现语句为: from 模块名 import *** as 别名 ,该命令为导入的对象起一个别名。这样就可以通过别名来使用对象。例如:

from utils import max_num as max_n, min_num as min_n

print(max_n(4, 5))
print(min_n(4, 5))
1
2
3
4

在上面的例子中,分别为 max_num,min_num 取了别名 max_n,min_n。这样在调用函数时,便可以使用 max_n,min_n

#2.4 import <module_name> as <alt_name>

我们还可以为导入的整个模块起一个别名,这样便可以通过模块的别名来使用模块,使用方法是一样的,都是将 模块名. 作为前缀。例如:

import utils as ul

print(ul.max_num(4, 5))
print(ul.min_num(4, 5))
1
2
3
4

在上面的例子中,为模块 utils 取了别名 ul,这样在调用函数时,便可以使用 ul. 前缀。

#2.5 包含单个类的模块

我们一起来看下包含单个类的模块,我们创建一个模块(car.py),包含类 car ,语句如下:

class Car:
    def __init__(self, mk, md, y, c):
        self.make = mk
        self.model = md
        self.year = y
        self.color = c
        self.mileage = 0

    def get_description(self):
        description = f'{self.year} {self.color} {self.make} {self.model}'
        print(description)

    def get_mileage(self):
        print(f"This car has {self.mileage} miles on it")

    def update_mileage(self, mile):
        self.mileage = mile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

导入类(my_car.py):

from car import Car

my_car = Car('audi', 'a4', 2016, 'white')
my_car.get_description()
my_car.update_mileage(30)
my_car.get_mileage()
1
2
3
4
5
6

#2.6 包含多个类的模块

我们创建模块(car.py),其中包含父类 car 和继承类 Electriccar ,语句如下:

class Car:
    def __init__(self, mk, md, y, c):
        self.make = mk
        self.model = md
        self.year = y
        self.color = c
        self.mileage = 0

    def get_description(self):
        description = f'{self.year} {self.color} {self.make} {self.model}'
        print(description)

    def get_mileage(self):
        print(f"This car has {self.mileage} miles on it")

    def update_mileage(self, mile):
        self.mileage = mile


class ElectricCar(Car):
    def __init__(self, mk, md, y, c):
        super().__init__(mk, md, y, c)
        self.battery_size = 100

    def get_battery(self):
        print(f"This car has {self.battery_size} -kWh battery.")
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

导入单个类(my_electirc_car.py):

from car import ElectricCar

my_tesla = ElectricCar('tesla', 'model 3', 2018, 'white')
my_tesla.get_description()
my_tesla.get_battery()
1
2
3
4
5

导入多个类(my_cars.py):

from car import ElectricCar, Car

my_car = Car('audi', 'a4', 2016, 'white')
my_car.update_mileage(30)
my_car.get_mileage()

my_tesla = ElectricCar('tesla', 'model 3', 2018, 'white')
my_tesla.get_description()
my_tesla.get_battery()
1
2
3
4
5
6
7
8
9

导入整个模块:

import car

my_car = car.Car('audi', 'a4', 2016, 'white')
my_car.update_mileage(30)
my_car.get_mileage()

my_tesla = car.ElectricCar('tesla', 'model 3', 2018, 'white')
my_tesla.get_description()
my_tesla.get_battery()
1
2
3
4
5
6
7
8
9

导入模块中的全部类:

from car import *

my_car = Car('audi', 'a4', 2016, 'white')
my_car.update_mileage(30)
my_car.get_mileage()

my_tesla = ElectricCar('tesla', 'model 3', 2018, 'white')
my_tesla.get_description()
my_tesla.get_battery()
1
2
3
4
5
6
7
8
9

#3 包

仓颉在创造出文字之前,也摸索了很多办法,他先是在绳子上打结,用各种不同颜色的绳子,表示各种不同的牲口。但时间一长,就不奏效了。增加的数目在绳子上打个结很方便,而减少数目时,在绳子上解个结就麻烦了。仓颉又想到了在绳子上打圈圈,在圈子里挂上各式各样的贝壳,来代替他所管的东西。增加了就添一个贝壳,减少了就去掉一个贝壳。但是随着仓颉管理事情的增多,这个方法也不好用了,他只能寻找其他办法,有一天,他看到猎人用动物的脚印来判断动物的踪迹,受到启发,创造了用符号表示事物,也就是文字。

在程序中呢,也会遇到和仓颉一样的问题,就是假设我们开发了一个很庞大的应用程序,程序包含了非常多的模块。随着模块数量的增长,如果将模块都放在同一个目录下,将变得越来越难管理。特别当模块具有相似的名称或相似的功能。这时候我们非常希望对这些模块进行分组管理,Python 中的包实现了对模块分组管理的功能。包的创建非常简单,它利用了操作系统的分层文件结构。我们只要将模块放在一个目录下便可。

e4028046867cd56664b05014d8925de4

在上图中,目录 pkg 下有两个模块,utils1.py 和 utils2.py,pkg 便是一个包。(包相当于一个文件夹,模块则相当于文件夹中的文件)

两个模块中的语句如下:(语句相当于文件中的内容)

utils1.py:

def max_num(a, b):
    if a >= b:
        return a
    else:
        return b


def min_num(a, b):
    if a > b:
        return b
    else:
        return a
1
2
3
4
5
6
7
8
9
10
11
12

utils2.py:

def sum_num(a, b):
    return a + b


def abs_num(a):
    if a >= 0:
        return a
    else:
        return -a
1
2
3
4
5
6
7
8
9

#3.1 import <module_name>[, <module_name> ...]

导入包中的模块,语法规则为:import 包.模块名,我们一起看下方语句:

import pkg.utils1
import pkg.utils2

print(pkg.utils1.max_num(4, 5))
print(pkg.utils2.sum_num(4, 5))
1
2
3
4
5

导入包 pkg 中的模块 utils1 和模块 utils2,并调用两个模块中的方法,将 pkg.utils1. 作为前缀放在 max_num()方法前,表示是在 pkg 包中的模块 utils1 内的方法。

#3.2 from <package_name> import <modules_name>[, <module_name> ...]

我们也可以通过 from 语句来实现模块的导入,我们一起看下方语句:

from pkg import utils1, utils2

print(utils1.max_num(4, 5))
print(utils2.sum_num(4, 5))
1
2
3
4

#3.3 from <module_name> import <name(s)>

我们再来一起看下,定义包之后,导入指定模块中的对象,我们看下方语句:

from pkg.utils1 import max_num

print(max_num(4, 5))
1
2
3

和第二部分模块导入相比,就是在模块名前将包的名字作为前缀 pkg.utils1 来实现的,其余语句均与模块导入一致。

#3.4 from <module_name> import  as <alt_name>

为模块内的对象和方法设置别名,语句如下:

from pkg.utils1 import max_num as max_n

print(max_n(4, 5))
1
2
3

#3.5 from <package_name> import <module_name> as <alt_name>

为导入的整个模块设置别名,语句如下:

from pkg import utils1 as ul1

print(ul1.max_num(4, 5))
1
2
3

#4 总结

本关,我们主要给大家介绍了模块和包,我们一起来回顾下本关内容:

ed025f702b1990479d54567bf7b12d3c

#5 练习题

自定义一个模块,并在另一个文件中导入这个模块。

第十三章异常处理

我们先来一起回顾下上关内容,上一关,我们为大家介绍了模块和包。

ed025f702b1990479d54567bf7b12d3c-1

今天,我们来介绍 Python 中的异常处理,我们先来一起了解下什么是异常?

#1 什么是异常?

嫦娥本是后羿之妻,后羿射下 9 个太阳后西王母赐其不老仙药,但后羿不舍得吃下,就交于嫦娥保管。后羿门徒蓬蒙觊觎仙药,逼迫嫦娥交出仙药,嫦娥无奈情急之下吞下仙药,便向天上飞去。

在嫦娥奔月的这个故事中,后羿的门徒蓬蒙等人觊觎仙药,就是一个异常,因为他们本身的品性不好, 如果再吃了长生不老的仙药,会对世间造成很大的危害;嫦娥无奈之下吞下仙药,便是对异常情况的一个处理,为了让异常情况不产生负面影响所采取的措施。

在 Python 中,异常是在程序运行过程中发生的错误,当异常发生时,需要对异常进行处理,否则整个程序将崩溃

举个例子:

print(1 / 0)
print("Done!")
1
2

例子中的 1 / 0 触发了 ZeroDivisionError 异常,由于没有对异常进行处理,导致了程序的崩溃,后面的语句没有再继续执行。

#2 异常的处理

当异常发生时,如果直接导致了程序的崩溃,不论对用户还是对开发者来说都是不友好的,这便要求我们在异常发生时,对异常进行处理。就像嫦娥一样,当发现品性不好的蓬蒙等人觊觎仙药时,为了阻止不好的情况发生,吞服了仙药,对异常进行了及时的处理。

下面,我们来看下如何进行异常的处理?

#2.1 try-except

try  和 except 语句块可以用来捕获和处理异常,try 后面跟的是需要捕获异常的代码,except 后面跟的是捕获到异常后需要做的处理。每一个 try 语句块后面必须跟上一个 except 语句块,即使 except 语句块什么也不做。

ec2d22bb252671a6f9892c112a17c28a

举个例子:

try:
    print(1 / 0)
except ZeroDivisionError:
    print("ZeroDivisionError happened!")

print("Done!")
1
2
3
4
5
6

加了异常捕获和处理代码之后,当发生异常时,整个程序没有崩溃,而是继续执行后面的代码,所以输出了 Done!。大家要注意冒号及缩进哈!

try 语句块后面可以跟上多个 except 语句块。

try:
    print(1 / 0)
    #除0异常
    with open('test.log') as file:
    #文件不存在异常
        read_data = file.read()
except ZeroDivisionError:
    print("ZeroDivisionError happened!")
except FileNotFoundError:
    print("FileNotFoundError happened!")

print("Done!")
1
2
3
4
5
6
7
8
9
10
11
12

在执行代码 print(1 / 0) 时,发生了除 0 异常,所以没有执行后面的打开文件的代码,后面的异常处理代码输出了 ZeroDivisionError happened!

如果我们颠倒下代码的顺序:

try:
    with open('test.log') as file:
    #文件不存在异常
        read_data = file.read()
    print(1 / 0)
    #除0异常
except ZeroDivisionError:
    print("ZeroDivisionError happened!")
except FileNotFoundError:
    print("FileNotFoundError happened!")

print("Done!")
1
2
3
4
5
6
7
8
9
10
11
12

代码颠倒之后,在执行打开文件的代码时,发生了文件不存在的异常,所以没有执行后面的代码,后面的异常处理代码输出了 FileNotFoundError happened!

#2.2 try-except-else

try-except 语句块后面可以跟上 else 语句块,当没有异常发生时,会执行 else 语句块中的代码。

7749ef169d827581b8a6b0db3e22e82d

举个例子:

try:
    print(1 / 1)
except ZeroDivisionError:
    print("ZeroDivisionError happened!")
else:
    print("Exception not happened")

print("Done!")
1
2
3
4
5
6
7
8

程序中没有发生异常,所以执行 else 语句块中的代码,输出了 Exception not happened

#2.3 try-except-else-finally

try-except-else 语句块后面还可以跟上 finally 语句块,不管有没有发生异常,finally 语句块中的代码都会被执行。

ed4f2613b609c174f818eec9b48aae30

举个例子:

  • 没有发生异常时
try:
    print(1 / 1)
except ZeroDivisionError:
    print("ZeroDivisionError happened!")
else:
    print("Exception not happened")
finally:
    print("Finally is executed!")

print("Done!")
1
2
3
4
5
6
7
8
9
10

没有发生异常时,除了执行 else 语句块中的代码,输出了 Exception not happenedfinally 语句块中的代码也得到了执行,输出了 Finally is executed! 。

  • 发生异常时
try:
    print(1 / 0)
except ZeroDivisionError:
    print("ZeroDivisionError happened!")
else:
    print("Exception not happened")
finally:
    print("Finally is executed!")

print("Done!")
1
2
3
4
5
6
7
8
9
10

发生异常时,finally 语句块中的代码同样得到了执行,输出了 Finally is executed! 。因此,不管有没有发生异常,finally 语句块中的代码都会被执行。finally 在释放资源时会特别有用。

#3 抛出异常

前面讲的是异常出现时,可以做的处理。另外,我们也可以主动抛出异常。主动抛出异常使用 raise 关键字。举个例子:

x = 10
if x > 5:
    raise Exception('x should not exceed 5. The value of x was: {}'.format(x))
1
2
3

当 x > 5 时,主动抛出异常。

#4 总结

5107e2b5278c15a12791c1efe53166e1

#5 练习题

打开一个不存在的文件,对发生的异常进行处理。

第十四章练习题

转眼间,我们的课程进入到了尾声阶段,不知道大家在课程的学习过程中有没有感受到 Python 的魅力呢!

最后一关,我们来一场华丽的华山论剑,我们将前面十三关的重要知识点浓缩成下面两个问题,大家一起来比拼下 Python 的武力值,为我们的课程画上一个完美的句号。

  1. 实现一个猜数字游戏,首先使用 random 模块中的随机函数生成一个位于 [1, 100] 范围内的数字,然后让机器人玩家来猜,比较机器人玩家猜的数字和生成的随机数,如果随机数大于玩家猜的数字告诉玩家猜的数字过小,如果随机数小于玩家猜的数字告诉玩家猜的数字过大,直到玩家猜到正确的数字。

提示:生成 1~100 的随机数可以使用 random.randint(1, 100)

  1. 实现一个剪刀、石头、布的游戏,首先使用 random 模块的函数从列表 ['剪刀', '石头', '布'] 中随机选择一个,然后机器人玩家也随机出一个,比较两个,判断玩家是输是赢。最后给出机器人玩家赢了几次,输了几次,平了几次。

提示:从列表 '剪刀', '石头', '布'] 随机选择,可以使用 random.choice(['剪刀', '石头', '布']

© 版权声明
THE END
喜欢就支持一下吧
点赞12 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片快捷回复

    暂无评论内容