机器学习案例分析(基于Python语言)
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

1.2 Python基础

Python语言诞生于1990年,由荷兰CWI(Centrum Wiskunde&Informatica,数学和计算机研究所)的Guido van Rossum设计并领导开发。Python语言具有简单易学、免费开源、跨平台、高层语言、面向对象、丰富的库、胶水语言等优点,已在系统编程、图形界面开发、科学计算、文本处理、数据库编程、网络编程、Web开发、自动化运维、金融分析、多媒体应用、游戏开发、人工智能、网络爬虫等方面有着广泛的应用。

经过20多年持续不断的发展,Python语言经历了多个版本的更迭。目前使用的Python版本主要是Python2.x和Python3.x。但是Python3.x并不完全兼容Python2.x的语法,所以如果没有特殊应用需求,建议使用Python3.x版本。

1.2.1 Python编程环境

在Linux、Windows、MacOS等平台上,都可以安装Python语言环境以支持Python程序的运行。但由于每个人使用Python的应用场景不一样,设置Python、安装附加包,并没有一个统一的解决方案,这里将给出Windows和MacOS系统中详细的Python安装说明。Linux系统的安装细节取决于所用的Linux版本,这里不再详细介绍。在正式介绍Python环境搭建之前,先给出Anaconda的简单介绍。Anaconda是一个用于科学计算的Python/R发行版,支持Linux、Windows、MacOS系统,提供了包管理与环境管理的功能,可以很方便地解决多版本Python并存、切换及各种第三方包安装问题。使用Anaconda可以一次性地获得300多种用于科学和工程计算相关任务的Python编程库支持。

这里推荐使用免费的Anaconda发布版搭建Python环境,这样可以减少后续安装Python各种包的麻烦,读者可以从Anaconda官网的Download页面(https://www.anaconda.com/distribution/)下载安装包,如图1-2所示。

图1-2 Anaconda官网的Download页面

单击图1-2下方的不同系统图标,可以看到对应系统下最新的安装包,如图1-3所示是Windows系统下的Anaconda安装包。

图1-3 Windows系统下的Anaconda安装包

1.Windows

图1-3列出了Windows系统中可下载文件列表,推荐下载Python3.7版本。读者可以根据自己的操作系统版本选择下载32位安装包或64位安装包。安装包下载完成后,按照官网上的安装说明进行安装即可。

安装完成后需要确定所有设置是否正确。单击“开始”菜单,运行cmd命令,打开如图1-4所示的操作系统的命令提示符界面。通过输入Python命令可以启动Python解释器,此时进入Python控制台,并能看到所安装的Python版本信息(图1-4中显示的Python版本是3.7.3)。

图1-4 操作系统的命令提示符界面

提示图1-4中出现警告信息是因为没有激活Anaconda的虚拟环境。可以通过activate命令进入Anaconda设定的虚拟环境。如果activate后面什么参数都不加,则会进入Anaconda自带的base环境。

安装完成后会在“开始”菜单中多出以下几个应用。

Anaconda Navigator:用于管理工具包和环境的图形用户界面,后续涉及的众多管理命令也可以在Navigator中手工实现。

Anaconda Prompt:使用命令行界面来管理环境和包。

Jupyter Notebook:基于Web的交互式计算环境,可以编辑易于人们阅读的文档,用于展示数据分析的过程。本书中的全部示例程序都基于Jupyter Notebook运行,并展示运行结果。

Spyder:一个使用Python语言的跨平台的科学运算集成开发环境。

使用Anaconda Navigator启动应用程序,然后使用Spyder和Jupyter Notebook即可开始Python编程之旅。Anaconda Navigator的界面如图1-5所示。

图1-5 Anaconda Navigator的界面

2.MacOS

下载OS X版的Anaconda安装器,命名如Anaconda3-2019.03-MacOSX-x86_64.pkg。双击.pkg文件运行安装器。安装器运行时,会自动将Anaconda执行路径添加到系统的.bash_profile文件中,该文件位于/User/$USER/.bash_profile。

可以通过在系统命令行运行IPython来确认安装是否正常。

3.Linux

Linux下的安装细节取决于所用的Linux版本,本书不再详细介绍。

提示如果读者想安装Anaconda并不包含的额外的Python包,可以通过以下命令进行安装:

conda install package_name

如果上述命令不起作用,则可以使用pip包管理工具进行安装:

pip install package_name

还可以使用conda update命令来更新包:

conda update package_name

pip也支持通过-upgrade标识进行包的升级:

pip install-upgrade package_name

但是,当能够同时使用conda和pip进行包安装时,请不要尝试使用pip更新conda安装的包,否则可能会导致环境问题。

◎ 操作练习1-1

请在自己的系统中安装Anaconda,并通过Anaconda Navigator打开Jupyter Notebook,新建Python 3代码文件,并运行:

【操作步骤】

单击图1-5中Jupyter图标下方的Launch即可启动Jupyter Notebook,在浏览器出现的界面中选择New→Python 3,即可新建Python 3代码文件,如图1-6所示。

图1-6 新建Python 3代码文件

运行结果如图1-7所示(输入代码后,单击图1-7中工具栏上的“运行”即可)。

图1-7 操作练习1-1运行结果示例

提示在Jupyter Notebook中可以选择File→Save as将当前界面中输入的代码保存为.ipynb文件,该文件中不仅保存了代码,而且保存了运行结果。如果要恢复上次的运行环境,直接打开对应的.ipynb文件即可。也可以直接单击左上角Jupyter旁边的默认文件名(图1-7中所示为Untitled),直接将该文件重命名(推荐使用该方式)。

Jupyter Notebook默认保存为.ipynb格式的文件,如果需要保存为.py格式的Python脚本文件,则可以选择File→Download as→Python (.py)。

Jupyter Notebook的默认工作路径是当前用户的路径,由于用户路径在系统盘中,因此会有一些操作权限限制。建议读者在使用Jupyter Notebook前,重新设置工作路径。

◎ 操作练习1-2

请将Jupyter Notebook的工作路径设置为d:\jupyter-notebook。

【操作步骤】

(1)在“开始”菜单中运行Anaconda Prompt,打开如图1-8所示的Anaconda命令提示符界面,输入命令:jupyter notebook-generate-config。运行后,可看到生成的Jupyter Notebook配置文件路径(图1-8显示的路径是C:\Users\admin\.jupyter\jupyter_notebook_config.py)。

图1-8 Anaconda命令提示符界面

(2)使用文本编辑器(如“记事本”等)编辑Jupyter Notebook配置文件,在文件中搜索c.NotebookApp.notebook_dir,在下面加一行,将Jupyter Notebook的工作路径设置为d:\jupyter-notebook,如图1-9所示。需要注意,工作路径必须已存在,如果不存在,则无法正常启动Jupyter Notebook。因此,请在设置工作路径前在D盘创建jupyter-notebook文件夹。

图1-9 修改Jupyter Notebook工作路径

(3)重新启动Jupyter Notebook,设置生效。重新完成操作练习1-1后,可以在d:\jupyter-notebook目录下看到创建的.ipynb文件。

1.2.2 基本数据类型

一种编程语言所支持的数据类型决定了该编程语言所能保存的数据。Python语言常用的内置数据类型包括Number(数字)、String(字符串)、List(列表)、Tuple(元组)、Set(集合)和Dictionary(字典)。

1.Number

Python中有3种不同的数字类型,分别是int(整数类型)、float(浮点类型)和complex(复数类型)。

整数类型与数学中的整数概念一致。整型数字包括正整数、0和负整数,不带小数点,无大小限制。整数可以使用不同的进制表示:不加任何前缀为十进制整数;加前缀0o为八进制整数;加前缀0x则为十六进制整数。

浮点类型与数学中实数的概念一致,表示带有小数的数值。Python语言要求所有浮点数必须带有小数部分,小数部分可以是0,这种设计可以区分浮点数和整数。浮点数有两种表示方法:十进制表示和科学计数法表示。

复数类型表示数学中的复数。复数由实部和虚部组成,每一部分都是一个浮点数,其书写方法如下:

a+bj或a+bJ

其中,a和b是两个数字,j或J是虚部的后缀,即a是实部,b是虚部。

Python中提供了9个基本的数值运算操作符,如表1-1所示。

表1-1 9个基本的数值运算操作符

◎ 操作练习1-3

请按图1-10所示输入代码并运行。

图1-10 算术运算示例

2.String

文本在程序中用字符串(String)类型来表示。Python语言中只有用于保存字符串的String类型,而没有用于保存单个字符的数据类型。Python中的字符串可以写在一对单引号中,也可以写在一对双引号或一对三引号(三个连续的单引号或三个连续的双引号)中。其中,单引号和双引号都可以表示单行字符串,两者作用相同。使用单引号时,双引号可以作为字符串的一部分;使用双引号时,单引号可以作为字符串的一部分。三引号可以表示单行或者多行字符串。

不包含任何字符的字符串,如''(一对单引号)或""(一对双引号),称为空字符串(简称空串)。

在字符串中,可以使用转义字符,常用的转义字符如表1-2所示。

表1-2 常用的转义字符

◎ 操作练习1-4

请按图1-11所示输入代码并运行。提示:在Jupyter Notebook的Python代码编辑页面中选择View→Toggle Line Numbers即可进行是否显示行号的切换。

图1-11 创建字符串示例

如果取消s2(第3行)和print(s2)(第8行)前的注释符,程序会报SyntaxError错误。

利用下标“[]”可以从字符串中截取一个子串,其语法格式如下:

s[beg:end]

其中,s为原始字符串,beg是要截取子串在s中的起始下标,end是要截取子串在s中的结束下标。省略beg,则表示从s的开始字符进行子串截取,等价于s[0:end];省略end,则表示截取的子串包含从beg位置到最后一个字符之间的字符(包括最后一个字符);beg和end都省略,则表示子串中包含s中的所有字符。

注意 s[beg:end]截取子串中包含的字符是s中从beg至end-1(不包括end)位置上的字符。

Python中,对字符串中字符的下标有两种索引方式:从前向后索引和从后向前索引。如图1-12所示,从前向后索引方式中第1个字符的下标为0,其他字符的下标是前一个字符的下标加1;从后向前索引方式中,最后一个字符的下标为-1,其他字符的下标是后一个字符下标减1。

图1-12 字符串索引方式示例

◎ 操作练习1-5

请按图1-13所示输入代码并运行。

图1-13 字符串操作示例

Python提供了5个基本的字符串操作符,如表1-3所示。

表1-3 5个基本的字符串操作符

3.List

List(列表)是Python中一种非常重要的数据类型。列表中可以包含多个元素,且元素类型可以不同。每一个元素可以是任一数据类型,包括数字、字符串、列表及后面要介绍的元组、集合、字典。所有元素都写在一对方括号中,每两个元素之间用逗号分隔。不包含任何元素的列表([])称为空列表。

列表中元素的索引方式与字符串中元素的索引方式完全相同,也支持从前向后索引和从后向前索引两种方式。

◎ 操作练习1-6

请按图1-14所示输入代码并运行。

图1-14 列表操作示例

4.Tuple

Tuple(元组)与列表类似,可以包含多个元素,且元素类型可以不相同,书写时每两个元素之间用逗号分隔。与列表不同之处在于:元组的所有元素都写在一对小括号中,且元组中的元素不能修改。不包含任何元素的元组(())称为空元组。

元组中元素的索引方式与列表和字符串中元素的索引方式完全相同。

◎ 操作练习1-7

请按图1-15所示输入代码并运行。

图1-15 元组操作示例

5.Set

与元组和列表类似,Set(集合)中同样可以包含多个不同类型的元素,但集合中的各元素无序,不允许有相同值的元素,并且元素必须是可哈希(Hashable)对象。集合的主要作用是进行元素的快速检索,以及进行交集、并集等集合运算。

集合中所有元素都写在一对大括号中,各元素之间用逗号分隔。不包含任何元素的集合称为空集合。需要注意,创建空集合需要使用set函数,直接写{}表示创建一个空字典。

◎ 操作练习1-8

请按图1-16所示输入代码并运行。

图1-16 创建集合示例

6.Dictionary

Dictionary(字典)是另一种无序的对象集合。但与集合不同,字典是一种映射类型,每一个元素是一个键(key):值(value)对。在一个字典对象中,键必须是唯一的,即不同元素的键不能相同;键必须是可哈希数据,即键不能是列表、元组、集合、字典等类型;值可以是任意类型。字典中的所有元素(键:值对)都写在一对大括号中,各元素之间用逗号分隔。不包含任何元素的字典({})称为空字典。

创建字典时,既可以使用大括号,也可以使用dict函数。如果要创建一个空字典,可以使用{}或dict(),如图1-17所示。

图1-17 创建空字典

◎ 操作练习1-9

请按图1-18所示输入代码并运行。

图1-18 创建字典示例

提示zip函数的参数是多个可迭代的对象(列表等),其功能是将不同对象中对应的元素分别打包成元组,然后返回由这些元组组成的列表。在Python3.x中为了减少内存,zip函数返回的是一个对象,可以通过list函数转换成列表,如通过list(zip(['one','two','three'],[1,2,3]))可得到列表[('one',1),('two',2),('three',3)]。

1.2.3 分支语句和循环语句

程序由3种基本结构组成:顺序结构、分支结构和循环结构。这些基本结构都有一个入口和一个出口。

● 顺序结构是程序按照线性顺序依次执行的一种运行方式。

● 分支结构是程序根据条件判断结果而选择不同向前执行路径的一种运行方式,根据分支路径上的完备性,分支结构包括单分支结构、二分支结构和多分支结构。

● 循环结构是程序根据条件判断结果向后反复执行的一种运行方式,根据循环体触发条件不同,循环结构包括条件循环结构和遍历循环结构。

1.分支语句

分支语句是控制程序运行的一类重要语句,它的作用是根据判断条件选择程序执行路径,使用方式如下:

其中,if、elif、else都是保留字,else后面不设置条件,表示不满足if和elif语句的其他情况。最简单的条件语句只有if,elif和else都是可选项,根据需要决定是否使用。

◎ 操作练习1-10

请按图1-19所示输入代码并运行。

图1-19 if、elif和else语句使用示例

其中,第2行if语句包含第一个条件表达式,当表达式返回True时,执行第3条语句,如果返回False,则执行第4行的elif语句,判断下一个条件。同理,如果条件成立,则继续执行第5行语句,否则执行第6行语句。如果所有if、elif条件都不满足,则执行第10条else语句,该语句表示用户输入的成绩在大于90且小于或等于100的范围内。

2.循环语句

循环语句是控制程序运行的一类重要语句,与分支语句控制程序执行类似,它的作用是根据判断条件确定一段程序是否再次执行一次或者多次。

循环结构流程图如图1-20所示。其中,语句序列1和语句序列3分别是循环语句前和循环语句后所执行的操作。循环条件判断和语句序列2构成了循环语句:只要满足循环条件,就会执行循环语句2;执行循环语句2后,会再次判断是否满足循环条件。

图1-20 循环结构流程图

这里介绍Python中两种循环语句的使用方法:for循环和while循环。

1)for循环

Python语言中的for循环用于遍历可迭代对象中的每一个元素,并根据当前访问的元素做数据处理,其语法格式如下:

变量依次取可迭代对象中每一个元素的值,在语句序列中可以根据当前变量保存的元素值进行相应的数据处理。

◎ 操作练习1-11 使用for循环遍历列表

按图1-21所示输入代码并运行。

图1-21 for循环使用示例

2)while循环

Python中while循环的语法格式如下:

当循环条件返回True时,执行语句序列;执行语句序列后,再判断循环条件是否成立。

◎ 操作练习1-12 使用while循环求n!

按图1-22所示输入代码并运行。

图1-22 while循环使用示例

运行程序后,如果输入5,则输出120;如果输入7,则输出5040。

1.2.4 函数

函数可以理解为对一组表达特定功能表达式的封装,它与数学函数类似,能够接收变量并输出结果。在Python中,函数是实现模块化的工具。

1.函数的定义与调用

Python语言中使用函数分为两个步骤:定义函数和调用函数。

Python语言中定义函数需要使用def关键字,下面通过一个简单的例子直观地了解定义和调用函数的过程。

◎ 操作练习1-13 函数定义和调用示例

按图1-23所示输入代码并运行。

图1-23 函数定义和调用示例

2.参数列表和返回值

通过函数的参数列表,可以为函数传入待处理的数据,从而使一个函数更加通用。

1)形参

形参的全称是形式参数,即定义函数时函数名后面的一对小括号中给出的参数列表。形参只能在函数中使用,其作用是接收函数调用时传入的参数值,并在函数中参与运算。

2)实参

实参的全称是实际参数,即调用函数时函数名后面一对小括号中给出的参数列表。当调用函数时,会将实参的值传递给对应的形参,函数中再利用形参进行运算,得到结果。

3)默认参数

函数的默认参数就是缺省参数,即当调用函数时,如果没有为某些形参传递对应的实参,则这些形参会自动使用默认参数值。

4)关键字参数

在调用函数时,除了前面那种通过位置来体现实参和形参的对应关系的方法(位置参数),还有一种使用关键字参数的方法,其形式为“形参=实参”。

在使用关键字参数调用函数时,实参的传递顺序可以与形参列表中形参的顺序不一致。这样,当一个函数的很多参数都有默认值,而只想对其中一小部分带默认值的参数传递实参时,就可以直接通过关键字参数的方式来进行实参传递,而不必考虑这些带默认值的参数在形参列表中的实际位置。

5)不定长参数

不定长参数,即在调用函数时可以接收任意数量的实参,这些实参在传递给函数时会被封装成元组(位置参数)或字典(关键字参数)形式。一般情况下,不定长参数放在形参表的最后,前面传入的实参与普通形参一一对应,而后面剩余的实参会在被封装成元组或字典后传给不定长参数。

6)拆分参数列表

如果一个函数所需要的参数已经存储在列表、元组或字典中,就可以直接从列表、元组或字典中拆分出函数所需要的参数,其中列表、元组拆分出来的结果作为位置参数,而字典拆分出来的结果作为关键字参数。

7)返回值

通过返回值,可以将函数的计算结果返回到函数调用的位置,从而可以利用函数调用返回的结果再去进行其他运算。前面的很多例子中都利用了print函数将计算结果输出在屏幕上,但无法再获取这些显示在屏幕上的结果以参与其他运算。如果希望一个函数的运算结果返回到调用函数的位置,从而可以继续用该结果参与其他运算,那么应使用return语句。

8)lambda函数

lambda函数也称匿名函数,是一种不使用def定义函数的形式,其作用是能快速定义一个简短的函数。lambda函数的函数体只是一个表达式,所以lambda函数通常只能实现比较简单的功能。其语法格式为

lambda [参数1[,参数2,…,参数n]]:表达式

冒号后面的表达式的计算结果即该lambda函数的返回值。

◎ 操作练习1-14 形参、实参和返回值示例

按图1-24所示输入代码并运行。

图1-24 形参、实参和返回值示例

◎ 操作练习1-15 默认参数、关键字参数、不定长参数示例

按图1-25所示输入代码并运行。

图1-25 默认参数、关键字参数、不定长参数示例

◎ 操作练习1-16 拆分参数列表示例

按图1-26所示输入代码并运行。

图1-26 拆分参数列表示例

◎ 操作练习1-17lambda函数示例

按图1-27所示输入代码并运行。

图1-27 lambda函数示例

1.2.5 类和对象

类与对象是面向对象程序设计的两个重要概念。类和对象的关系即数据类型与变量之间的关系,使用一个类可以创建多个对象,而每个对象只能是某一个类的对象。类规定了可以用于存储什么数据,而对象用于实际存储数据。

1.类的基本概念

一个类中可以包含属性和方法。属性对应一个类可以保存哪些数据,而方法对应一个类可以支持哪些操作。对象是类的实例。

提示类中的属性对应前面所学习的变量,而类中的方法对应前面所学习的函数。通过类,可以把数据和操作封装在一起,从而使得程序结构更加清晰,这也就是所谓的类的封装性。

1)创建类

使用class语句来创建一个新类,class之后为类的名称,并以冒号结尾。其形式如下:

class_suite由类成员、方法和数据属性组成。

定义了一个类后,就可以创建该类的实例对象,其语法格式如下:

类名(参数表)

◎ 操作练习1-18 创建一个空类

按图1-28所示输入代码并运行。

图1-28 创建一个空类

从输出结果可以看到,em是Employee类的对象,其地址为0x0000000005D26588。注意,因为每次运行时给对象分配的内存空间可能不同,所以输出的对象地址也会有所不同。

2)类属性及其访问

一个类中可以包含属性和方法,属性对应一个类对象可以保存的数据。可以在定义类时指定该类的属性。

对类属性的访问,既可以通过类名进行,也可以通过该类的对象进行,访问形式如下:

类名或对象名.属性名

◎ 操作练习1-19 类属性访问示例

按图1-29所示输入代码并运行。

图1-29 类属性访问示例

提示从图1-29可以看出,既可以获取类属性的值,也可以对类属性赋值。

当创建新对象时,该对象中的类属性的值即定义类时给类属性赋的值。

当使用类名对类属性值做修改后,如果对象的该属性没有被重新赋值,则对象的属性值也会随之修改;如果对象的该属性已被重新赋值,则对象的属性值不会随之修改。

当使用对象名对属性值做修改后,只会改变该对象的属性值,类和其他对象的该属性值不会随之修改。

3)类中的方法

类中的方法分为两类:普通方法和内置方法。普通方法需要通过类的实例对象根据方法名调用,内置方法是指在特定情况下由系统自动执行。

普通方法要求第一个参数必须对应调用方法时所使用的实例对象(一般命名为self,也可以改为其他名字)。当使用一个实例对象调用类的普通方法时,其语法格式如下:

实例对象名.方法名(实参列表)

常用的内置方法包括构造方法、析构方法、__str__方法等。

● 构造方法:其方法名为__init__,在创建一个类对象时会自动执行,负责完成新创建对象的初始化工作。

● 析构方法:其方法名为__del__,在销毁一个类对象时会自动执行,负责完成待销毁对象的资源清理工作。

●__str__方法:在调用str函数对类对象进行处理时或者调用Python内置的format和print函数时自动执行,__str__方法的返回值必须是字符串。

◎ 操作练习1-20 类的构造方法示例

按图1-30所示输入代码并运行。

图1-30 类的构造方法示例

2.继承与多态

除前面介绍的封装性以外,继承与多态是面向对象程序设计的另外两个重要特性。通过继承,可以基于已有类创建新的类,新类除了继承已有类的所有属性和方法,还可以根据需要增加新的属性和方法。通过多态,可以实现在执行同一条语句时,能根据实际使用的对象类型决定调用哪个方法。

1.2.6 打开、关闭、读/写文件

I/O编程可以将内存中的数据以文件的形式保存到外存中,从而实现数据的长期保存及重复利用。同时,也可以利用os模块方便地使用与操作系统相关的功能,如生成文件路径、创建不存在的目录,为文件读/写操作提供辅助支持。

1.打开和关闭文件

使用open函数可以打开一个要做读/写操作的文件,其常用形式如下:

其中,filename是要打开文件的路径;mode是打开文件的方式(表1-4),不同文件打开方式可以组合使用。使用open函数打开文件后会返回一个文件对象,利用该文件对象可完成文件中数据的读/写操作。

表1-4 文件打开方式

使用open函数打开文件并完成读/写操作后,必须使用文件对象的close方法将文件关闭。

使用with语句可以让系统在文件操作完毕后自动关闭文件,从而避免忘记调用close方法而不能及时释放文件资源的问题。

◎ 操作练习1-21 with语句使用示例

按图1-31所示输入代码并运行。

图1-31 with语句使用示例

2.文件读/写

使用open函数打开文件后,即可使用返回的文件对象进行文件读/写操作。下面介绍文件对象中读/写数据的几种方法。

1)write方法

使用文件对象的write方法可以将字符串写入文件中,其语法格式如下:

其中,f是open函数返回的文件对象,str是要写入文件中的字符串。write方法执行完毕后将返回写入文件中的字符个数。

2)read方法

使用文件对象的read方法可以从文件中读取数据,其语法格式如下:

其中,f是open函数返回的文件对象;n指定了要读取的字节数,默认值为-1,表示读取文件中的所有数据。read方法将从文件中读取的数据返回。

3)readline方法

使用文件对象的readline方法可以从文件中每次读取一行数据,其语法格式如下:

其中,f是open函数返回的文件对象。readline方法将从文件中读取的一行数据返回。

4)readlines方法

使用文件对象的readlines方法可以从文件中按行读取所有数据,其语法格式如下:

其中,f是open函数返回的文件对象。readlines方法将从文件中按行读取的所有数据以列表形式返回。

◎ 操作练习1-22 写文件示例

按图1-32所示输入代码并运行。

图1-32 写文件示例

打开文件D:\python\test.txt,可以看到如下文件内容:

即通过write方法向文件中写入了两行字符串。

◎ 操作练习1-23 读文件示例

按图1-33所示输入代码并运行。

图1-33 读文件示例

1.2.7 异常处理

异常是指因程序运行时发生错误而产生的信号。如果程序中没有对异常进行处理,则程序会抛出该异常,并停止运行。为了保证程序的稳定性和容错性,需要在程序中捕获可能的异常,并对其进行处理,使得程序不会因异常而意外停止。

Python通过try、except等保留字提供异常处理功能,其语法格式如下:

try的工作原理是,当开始一个try语句后,Python就在当前程序的上下文中做标记,这样当异常出现时就可以回到这里,try子句先执行,接下来会发生什么依赖于执行时是否出现异常。

● 如果try子句执行时发生异常,Python就会执行第一个匹配该异常的except子句。异常处理完毕,控制流就完成整个try语句的执行,继续执行try语句后面的代码(除非在处理异常时又引发新的异常)。

● 如果try子句执行时发生异常,却没有匹配的except子句,异常将被传递到上层的try语句,或者到程序的最上层(这样将结束程序,并打印默认的出错信息)。

● 如果try子句执行时没有发生异常,Python将执行else子句(如果有else的话);否则,else子句不会被执行。

● finally是try except语句的一个可选项。无论try子句执行时是否发生异常,finally子句都会被执行。

除系统提供的异常类型以外,还可以自定义异常。自定义异常是指除了系统提供的异常类型,还可以根据需要定义新的异常。自定义异常,实际上就是以BaseException类作为父类创建一个子类。

◎ 操作练习1-24 异常处理示例

按图1-34所示输入代码并运行。

图1-34 异常处理示例