第3章 Python 编程基础 本章主要为没有接触过或者正在学习Python编程的读者而设。不同于那些完整介 绍Python编程的书籍和课程,作者并没有做铺陈的打算,而是尝试从本书的总体需求和 特点出发,去粗取精,提炼“干货”,向读者介绍足以用来理解并且实践本书全部代码的 Python基础编程知识。 3.1 Python 编程环境配置 在开始学习具体的Python编程知识之前,需要先解决下面两个问题:“Python代码 在哪里写? 又在哪里运行?” 正所谓“工欲善其事,必先利其器”,目前在市场上,为Python代码提供编写和运行环 境的应用程序非常多。如果从是否具备实时的交互性、是否能够支持远程的编写和运行 服务、是否提供便捷开发的集成化功能和界面这三个维度来考量,那么Python的主流编 程环境可以分为三种,分别是基于命令行/终端的交互式编程环境、基于Web的交互式编 程环境,以及集成式开发环境。 接下来的各小节将分别就上述各个类别的开发环境进行举例说明。 3.1 基于命令行/终端的交互式编程环境 1. 基于命令行/终端的交互式编程环境是我们最容易接触到的。如图3.Python 1所示, 解释器本身就内置了一个交互式的编程环境。我们可以在Windows的命令提示符模式 或者macOS 和Linux的终端中,直接输入命令python调起Python解释器的默认编程 环境。 这种交互式编程环境的优点在于,几乎输入的每一行Python代码都会立刻得到程序 运行的反馈,便于人们了解每一行代码的执行情况。但是,这样做的缺点也非常明显:许 42Python机器学习及实践——从零开始通往Kaggle竞赛之路(2022年度版) 图3.n内置的交互式编程环境 1 Pytho 多大型程序的逻辑复杂,需要编写大量的代码,而不需要逐行查验程序输出。因此,这种 交互式编程环境适合培养新手入门,但是熟练的程序员却不常使用这种编程环境。 与Python解释器编程环境类似的代表性应用有IPytho如图3.1 thoIPython, 2所示。比起图3. 的Pyn内置编程环境,n算是一种增强型的终端交互式编程环境,对于一些 Python编程的语法、关键字和内置函数,都会用不同颜色的字符进行突出显示。 图3.交互式编程环境IPyhn 2 to 3.2 基于Web的交互式开发环境 1. 除了基于终端的交互式开发环境,目前基于Web的交互式开发环境更加流行。 JupyterNotebook就是这种Python开发环境的典型应用。如图3.这种类似于笔 3所示, 记一样的编程平台,也和IPython类似,能够立刻执行输入的程序,给出反馈。更进一步 地,对于大段的Python程序,也可以将其整体输入JupyterNotebook的文件中,并且整 段运行。 JupyterNotebootho 因此,k从一定程度上避免了IPyn的缺点,能够既保留交互式编 程环境的优点,同时也适用于大型程序的编写。但是,对于更加专业的程序设计人员, JupyterNotebook仍然无法提供更加高级的服务,如代码调试、内存中变量查看等其他 第 3 章 Python 编程基础43 功能。 图3.基于Web的交互式开发环境J 3 upyterNotebook 3.3 集成式开发环境 1. 集成式开发环境提供了更加专业的编程平台,除了能够为程序设计人员提供大型程 序所需要的源代码编写空间以外,同时也集成了诸如代码调试、内存变量管理、单元测试 等大量专业编程所需要的关键辅助功能。代表性的Python集成式开发环境包括 PyCharm 和Spyder,分别如图3.5所示。 4与图3. 图3.集成式开发环境PyCh 4 arm 44 Python 机器学习及实践——从零开始通往Kaggle 竞赛之路(2022 年度版) 图3.5 集成式开发环境Spyder 3.2 Python 基本语法 “简单、易学、优雅”是本书对于Python编程基础的评价。Python代码的可读性和撰 写效率在大量的编程语言(Java、C++等)中是首屈一指的。 毫不夸张地说,即便是没有任何编程基础的读者,初看一些Python编程的基础代码, 相信也能够勉强看懂其中的要旨。许多使用Python编写的程序只需要寥寥数行,就能够 实现十分强大的功能。上述这些特点得益于Python基础语法特性。 3.2.1 赋值 对程序变量进行赋值声明是任何编程语言中都要进行的基本操作。如果在程序中贸 然访问一个没有进行赋值声明的变量,如代码3.1所示,程序则会报错。 代码3.1 Python变量赋值的错误方式 In[*]: is_ML_Geek Out[*]: --------------------------------------------------------------------------- NameError Traceback (most recent call last) <ipython-input-2-97b21c2ef31d>in <module> .................................................................................. 第3 章 Python 编程基础 45 1 #直接查验未定义变量is_ML_Geek 的赋值,运行后程序报错 ---->2 is_ML_Geek NameError: name 'is_ML_Geek' is not defined 许多主流的高级编程语言,如C++、Java等,都需要在对变量进行赋值时声明变量的 数据类型。但是,Python不需要这样做。如代码3.2所示,Python中对变量的赋值声明 十分简单而且直接,只需要把具体的值通过“=”赋予所定义的变量名即可。 代码3.2 Python变量赋值的方式 In[*]: is_ML_Geek =True is_ML_Geek ..Ou..t[..*..]:..T..ru..e .................................................................... Python变量名的定义有一套十分明确的规则: ● 变量名可以由字母、数字,或者下画线(_)组成,其中数字不能作为开头; ● 变量名不能是Python的关键字,但可以包含关键字; ● 变量名不能包含空格。 其中,Python的关键字一般为许多内置的语句或者命令,如if、for、in等。这些关键 字在JupyterNotebook等专业编程环境中,一般都会用特殊的颜色突出显示,因此非常 容易规避。另外,只要在变量声明时考虑其未来的可读性,尽可能贴近变量的实际意义进 行命名,基本上都不太可能出现变量声明方面的错误。 3.2.2 注释 注释是代码可读性的另一层保障。与可执行的程序代码不同,注释不会被执行。如 代码3.3所示,Python编程语言的注释类型有两种:一种是单行注释,以“#”为行首,引 导整行的内容作为注释,不会被Python解释器执行;另一种是多行注释,使用三个单引号 或者三个双引号作为起始,直到对应的三个单引号或者双引号出现为止,中间的所有内容 均被视为注释。 代码注释是一种优良的编程习惯,也是一种程序员之间的“礼仪”,于人于己都有好 处,这个习惯非常建议读者保持。 46 Python 机器学习及实践——从零开始通往Kaggle 竞赛之路(2022 年度版) 代码3.3 Python注释样例 In[*]: #这是一个单行注释 ''' 这是使用三个单引号的 多行注释 ''' """ 这是使用三个双引号的 多行注释 """ 3.2.3 缩进 代码缩进是Python语言的特色规则之一。许多其他的高级编程语言(如C++、Java 等)不太关注代码的空白部分,代码的逻辑分割也大多使用其他标识符,如花括号、逗号 等。这些用于分割逻辑的标识符占用了过多的编程空间。Python则采用Tab缩进符,分 割代码的逻辑层次,显著减少了源代码的长度。 如代码3.4所示,if作为一个分支语句的关键字,提示后续的代码与其有从属的逻辑 层次,因此需要进行缩进操作。其他使用缩进Tab符的常见场景还包括for/while循环 语句、函数和类的声明等。 代码3.4 Python语句缩进的代码 In[*]: """ 如果变量is_ML_Geek 的赋值为True,那么程序会输出:"推荐您购买《Python 机器学习实 践:从零开始通往Kaggle 竞赛之路》!" """ if is_ML_Geek: print('推荐您购买《Python 机器学习实践:从零开始通往Kaggle 竞赛之路》!') ..Ou..t[..*..]:..推..荐..您..购..买..《P..yt..ho..n..机..器学..习..实..践..:..从..零..开..始..通..往..Ka..gg..le..竞..赛..之..路..》!................ 3.3 Python 数据类型 Python内置的常用数据类型共有7种,有简单的数值、布尔值、字符串,还有复杂一 些的元组、列表、集合,以及字典。 第3 章 Python 编程基础 47 另外,可以使用type()函数来直接查验具体的数据类型。比起其他的高级编程语 言,Python内置数据类型的种类简化了许多,具体介绍如下。 ● 数值(Number)。常用的数值类型包括整型数(Integer)、浮点数(Float)以及复数 (Complex)。整型数和浮点数是我们平时最常使用的两类,如代码3.5所示,读者 可以先简单地理解常用的整数,如10、100、-100等都是整型数;而一般用于计算 的小数,如-0.1、10.01等都可以使用Python的浮点数进行存储。复数在Python 中不太常用,因此不过多介绍。 代码3.5 Python常用数值类型样例 In[*]: type(10) #整型数 ..Ou..t[..*..]:..i..nt...................................................................... In[*]: type(0.34) #浮点数 ..Ou..t[..*..]:..f..lo..at.................................................................... In[*]: type(1+3j) #复数 ..Ou..t[..*..]:..c..om..pl..ex.................................................................. ● 布尔值(Boolean)。计算机的计算基础是二进制,因此任何一门编程语言都会有布 尔类型,用来表示真/假。如代码3.6所示,在Python中,这两个值有固定的表示: True代表真,False代表假。请读者切记,Python是大小写敏感的编程语言,因此 只有按照True或者False这样严格区分大小写的输入才会被解释器理解为布 尔值。 代码3.6 Python布尔值类型样例 In[*]: type(True) #布尔值:真 ..Ou..t[..*..]:..b..oo..l .................................................................... In[*]: type(False) #布尔值:假 ..Ou..t[..*..]:..b..oo..l .................................................................... ● 字符串(String)。字符串是由一系列字符(Character)组成的数据类型,应用范围 十分广泛,适用于文本数据的处理。如代码3.7所示,在Python中,字符串可以使 用成对的英文单引号或者双引号进行表示,如a' bc'或"123"。尽管123看似一个整 型数,但是一旦被成对的单引号或者双引号限制起来,便成为了字符串类型的 数据。 48 Python 机器学习及实践——从零开始通往Kaggle 竞赛之路(2022 年度版) 代码3.7 Python字符串数据类型样例 In[*]: type('abc') #用单引号声明的字符串 ..Ou..t[..*..]:..s..tr...................................................................... In[*]: type("123") #用双引号声明的字符串 ..Ou..t[..*..]:..s..tr...................................................................... 上述3类都是Python基本的内置数据类型,它们是数据表达与存储的基础。下面即 将介绍的4种数据类型则相对复杂,而且还需要上述3种基础数据类型的配合。 ● 元组(Tuple)。元组是一系列Python数据类型按照顺序组成的序列,使用一组圆 括号()表示。如代码3.8所示,(10,0.34,True,'abc')是一个包含4个元素的元 组。读者会发现,元组中的数据类型不必统一,这是Python的一大特点。另外, x_tuple[0]的值为10,x_tuple[1]的值为0.34。也就是说,我们可以通过索引直接 从元组中找到所需要的数据。特别需要提醒读者的是,大多数编程语言都默认索 引的起始值为0,而不是1。 代码3.8 Python元组数据类型样例 In[*]: x_tuple =(10, 0.34, True, 'abc') #将一个元组赋值给变量x_tuple print(x_tuple) ..Ou..t[..*..]:..(..10.., 0...3..4,..T..ru..e,..'..ab..c'..) .................................................. In[*]: type(x_tuple) #查验变量x_tuple 的数据类型 ..Ou..t[..*..]:..t..up..le.................................................................... ● 列表(List)。列表和元组在功能上是类似的,只是表示方法略有不同。如代码3.9 所示,列表使用一对方括号[]来组织数据,如:[10,0.34,True,a' bc']。读者需要 记住一点例外:Python允许在使用者在访问列表的同时修改列表里的数据,而元 组则不然。相关的样例代码会在3.4节中具体展示。 代码3.9 Python列表数据类型样例 In[*]: x_list =[10, 0.34, True, 'abc'] #将一个列表赋值给变量x_list print(x_list) ..Ou..t[..*..]:..[..10.., 0...3..4,..T..ru..e,..'..ab..c'..] .................................................. In[*]: type(x_list) #查验变量x_list 的数据类型 ..Ou..t[..*..]:..l..is..t .................................................................... 第3 章 Python 编程基础 49 ● 集合(Set)。Python使用一对花括号{}来初始化一个集合类型的数据。与列表和 元组不同,集合中不允许出现相同的元素。如代码3.10所示,即便初始化一个集 合时有重复的元素,但是,最终的集合只留下了不同的元素。 代码3.10 Python集合数据类型样例 In[*]: x_set ={10, 0.34, 'a', 'a', 'b'} #将一个集合赋值给变量x_set print(x_set) ..Ou..t[..*..]:..{..0...34.., 1..0,..'..b'.., ..'a..'}...................................................... In[*]: type(x_set) #查验变量x_set 的数据类型 ..Ou..t[..*..]:..s..et...................................................................... ● 字典(Dictionary)。字典是Python中非常实用而且功能强大的数据类型,特别在 数据处理任务中,字典几乎成为了数据存储的主流形式。从字典自身的数据结构 而言,它包括多组键(key)-值(value)对。如代码3.11所示,Python的字典数据类 型使用花括号{}来容纳这些键-值对,并且用英文冒号将键和值进行映射。特别需 要读者注意的是,字典中的键是唯一的,但是没有数据类型的限制。而查找某个键 所对应的值也和访问元组或者列表中元素的方式类似。例如,代码3.11中字典变 量x_dict的键包括1、2、a' '、a' bc';x_dict[a' ']的值为True。 代码3.11 Python字典数据类型样例 In[*]: #将一个字典赋值给变量x_dict x_dict ={1:10, 2:0.34, 'a':True, 'abc':'abc'} print(x_dict) ..Ou..t[..*..]:..{..1:..10..,..2:..0...3..4,..'a..':..T..ru..e,..'..ab..c'..: '..a..bc..'}.................................. In[*]: #查验变量x_dict 的数据类型 type(x_dict) ..Ou..t[..*..]:..d..ic..t .................................................................... 3.4 Python 数据运算 3.3节介绍了Python的数据类型,接下来,我们开始了解如何对这些数据进行运算。 Python中常用的数据运算类型有如下几种。 ● 算术运算(ArithmeticOperators)。毫无疑问,算术运算是作为一门编程语言所必 50 Python 机器学习及实践——从零开始通往Kaggle 竞赛之路(2022 年度版) 须具备的基础运算功能。Python中常用的算术运算符包括加法(+)、减法(-)、 乘法(*)、除法(/)、取余(%),以及幂(**)。代码3.12展示了各种算术运算的 样例。 代码3.12 Python算术运算样例 In[*]: 10 +20.0 #整型数与浮点数的加法,结果是浮点数 ..Ou..t[..*..]:..3..0...0 .................................................................... In[*]: 30-60 #整型数与整型数的减法,结果是整型数 ..Ou..t[..*..]:..-..30...................................................................... In[*]: 4 * 8 #整型数与整型数的乘法,结果是整型数 ..Ou..t[..*..]:..3..2 ...................................................................... In[*]: 4 * 8.9 #整型数与浮点数的乘法,结果是浮点数 ..Ou..t[..*..]:..3..5...6 .................................................................... In[*]: 5 / 4 #整型数除法,无论是否能够整除,结果都是浮点数 ..Ou..t[..*..]:..1...2..5 .................................................................... In[*]: 6 / 3 #整型数除法,无论是否能够整除,结果都是浮点数 ..Ou..t[..*..]:..2...0...................................................................... In[*]: 5 // 4 #除法,结果取整 ..Ou..t[..*..]:..1........................................................................ In[*]: 4 / 5 #除法,结果取整 ..Ou..t[..*..]:..0........................................................................ In[*]: 5%4 #取余运算 ..Ou..t[..*..]:..1........................................................................ In[*]: 2 ** 3 #幂运算 ..Ou..t[..*..]:..8........................................................................ ● 比较运算(ComparisonOperators)。如果说算术运算的返回值一般是数值类型, 那么比较运算则反馈布尔值类型的结果。代码3.13展示了常用于比较运算的运 算符和样例。 第3 章 Python 编程基础 51 代码3.13 Python比较运算样例 In[*]: 10 <20 #判断是否小于 ..Ou..t[..*..]:..T..ru..e .................................................................... In[*]: 10 >20 #判断是否大于 ..Ou..t[..*..]:..F..al..se.................................................................... In[*]: 10==10.0 #判断是否等于 ..Ou..t[..*..]:..T..ru..e .................................................................... In[*]: 10!=20 #判断是否不等于 ..Ou..t[..*..]:..T..ru..e .................................................................... ● 赋值运算(AssignmentOperators)。算术运算和比较运算都有一个共同的特点, 即所有的运算结果都只是作为一次性的输出。然而,在更多情况下,我们需要对数 据运算的中间结果进行存储,以备后续使用。因此,我们需要将一些数据赋值给自 定义的变量。赋值运算除了可以用于基本的Python变量初始化,也可以对已有的 变量值进行修改。如代码3.14所示,绝大多数的Python数据类型都可以通过赋 值运算进行修改,但是元组是一个例外。因此,元组和列表最大的不同在于:元组 类型的内部元素不可以被修改;而列表类型却可以。 代码3.14 Python赋值运算样例 In[*]: t =(1, 'abc', 0.4) t[0] =2 #元组类型的内部元素不可以被修改 Out[*]: --------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-16-64c6100d331f>in <module> 5 t =(1, 'abc', 0.4) 6 ---->7 t[0] =2 #元组类型的内部元素不可以被修改 TypeError: 'tuple' object does not support item assignment .................................................................................. In[*]: l =[1, 'abc', 0.4] #将一个列表赋值给变量l l[0] =2 #试图改变列表l 的第一个元素,并且重新赋值为2 52 Python 机器学习及实践——从零开始通往Kaggle 竞赛之路(2022 年度版) #对更新后的列表的第一个元素进行递增1 的操作,并重新赋值 l[0] +=1 l[0] #观察输出,结果应为3 ..Ou..t[..*..]:..3........................................................................ ● 逻辑运算(LogicalOperators)。逻辑运算比较简单,共有三种:与(and),或(or), 非(not)。逻辑运算所涉及的数据类型为布尔值,返回值也是布尔值。代码3.15 展示了部分常见逻辑运算的规则和结果。 代码3.15 Python逻辑运算样例 In[*]: True and True ..Ou..t[..*..]:..T..ru..e .................................................................... In[*]: #and 作为逻辑运算时,只要有一方为False,结果即为False True and False ..Ou..t[..*..]:..F..al..se.................................................................... In[*]: #or 作为逻辑运算符时,只要有一方为True,结果即为True True or False ..Ou..t[..*..]:..T..ru..e .................................................................... In[*]: #or 作为逻辑运算符时,两方均是False,结果才是False False or False ..Ou..t[..*..]:..F..al..se.................................................................... In[*]: #非(not)运算符用来反转布尔值 not True ..Ou..t[..*..]:..F..al..se.................................................................... ● 成员运算(MembershipOperators)。成员运算是针对Python中较为复杂的数据 结构而设立的一种运算,主要面向元组、列表、集合以及字典。如代码3.16所示, 我们可以借助运算符in,询问某个元素是否在元组、列表或者集合中出现,或者检 视某个键是否在字典中存在。这是Python中非常实用且功能强大的运算,适用 于数据处理任务。 第3 章 Python 编程基础 53 代码3.16 Python成员运算样例 In[*]: l =[1, 'abc', 0.4] #查询0.4 是否在列表l 中 0.4 in l ..Ou..t[..*..]:..T..ru..e .................................................................... In[*]: t =(1, 'abc', 0.4) #查询1 是否在元组t 中 1 in t ..Ou..t[..*..]:..T..ru..e .................................................................... In[*]: s ={1, 'abc', 0.4} #查询'abc'是否在集合s 中 'abc' in s ..Ou..t[..*..]:..T..ru..e .................................................................... In[*]: d ={1: '1', 'abc': 0.1, 0.4: 80} #查询0.4 是否在字典d 的键中 0.4 in d ..Ou..t[..*..]:..T..ru..e .................................................................... In[*]: 80 in d #尽管字典d 的值中有80,但是in 只负责键的查询 ..Ou..t[..*..]:..F..al..se.................................................................... 3.5 Python 流程控制 本章前几节的示例代码都是按照从前到后的常规顺序依次执行的。按照先后顺序执 行是最为常见的Python程序执行流程。然而,在某些情况下,我们需要选择执行或者重 复执行某些代码片段。这就需要通过一些特殊的流程控制,使得Python解释器具备可以 跳跃甚至回溯部分代码的能力。比较常见的流程控制方式包括分支语句(if-elif-else)和 循环控制(for/while)。 3.5.1 分支语句 很多情况下,我们需要程序根据不同的情况选择性地执行某一部分代码,这就需要分 支语句的参与。与分支语句紧密相连的数据类型和操作类型分别是布尔值与逻辑运算。 分支语句的关键字包括if、elif和else。常见的分支语句包括单独使用if、if-else搭 54 Python 机器学习及实践——从零开始通往Kaggle 竞赛之路(2022 年度版) 配,以及if搭配多个elif-else的情况。 如代码3.17所示,if-else的搭配最终只能选择if或者else两个分支之一的语句执 行;并且每一个分支语句都需要进行缩进处理。具体执行哪个分支,取决于if后续的布 尔值或者逻辑运算的结果是否为真。 代码3.17 Python分支语句if-else样例 In[*]: b =True if b: print("变量b 是真。") else: print("变量b 是假。") ..Ou..t[..*..]:..变..量..b..是..真..。.............................................................. if-elif-else的搭配如代码3.18所示。Python解释器会首先询问if对应的布尔值或 者逻辑运算为布尔值的表达式。如果为True,那么不会执行elif以及else对应的分支语 句;如果为False,则会依次试探elif对应的布尔值或者逻辑运算结果为布尔值的表达式。 以此类推,一旦其中任何一个为真,便会执行对应的多行分支语句,然后跳出整体分支语 句。如果if和elif中没有任何一个为真,则执行else对应的语句。 代码3.18 Python分支语句if-elif-else样例 In[*]: a =False b =False c =True if a: print("变量a 是真。") elif b: print("变量a 是假,并且变量b 是真。") elif c: """ 如果执行到此处,说明a 一定是False,同时b 一定是False,c 必须是真。 这是因为,分支语句依次执行真假判别。一旦某一分支判别为真,则该条语句被执行, 并且整体分支语句就会结束,根本没有机会执行后续其他的elif 和else。 """ print("变量a 是假,同时变量b 也是假,并且变量c 是真,这条语句才会被执行。") else: print("所有变量都是假!") .................................................................................. 第3 章 Python 编程基础 55 ..Ou..t[..*..]:..变..量..a..是..假..,同..时..变..量..b..也..是..假..,并..且..变..量..c..是..真..,这..条..语..句..才..会..被..执..行..。.............. 多个if引导的分支语句之间互不干涉,各自分别执行,如代码3.19所示。 代码3.19 Python多个分支语句样例 In[*]: """ 换一种情况,两个if 引导不同的两个分支语句,都会分别执行,互相不存在依赖关系。 """ a =False b =False c =True if not a: print("变量a 是假。") if b: print("变量b 是真。") elif c: print("变量b 是假,变量c 是真,这条语句才会被执行。") else: print("变量b 和c 都是假!") Out[*]: 变量a 是假。 变量b 是假,变量c 是真,这条语句才会被执行。 .................................................................................. 3.5.2 循环控制 还有一些情况,需要我们循环执行某些代码。这是计算机程序为人类提供的极大便 利,可以把某些具有规律的重复性代码单独封装。 循环控制可以根据需要采用for或while引导的两种不同的语法。如代码3.20所 示,以关键字for引导的循环控制,需要搭配之前介绍的成员运算符in形成固定的语法结 构,借助遍历来完成对循环语句的控制。 代码3.20 Python循环控制(for)样例 In[*]: d ={1: '1', 'abc': 0.1, 0.4: 80} for k in d: 56 Python 机器学习及实践——从零开始通往Kaggle 竞赛之路(2022 年度版) print(k, d[k]) Out[*]: 1 1 abc 0.1 0.4 80 .................................................................................. 而以关键字while引导的循环控制,如代码3.21所示,则需要在每一轮判定其后续的 布尔值或者逻辑表达式是否为真,从而决定是否要继续执行其循环语句。 代码3.21 Python循环控制(while)样例 In[*]: l =[1,2,3,4,5] i =0 while i <len(l): print(l[i]) i +=1 Out[*]: 12345 .................................................................................. 3.6 Python 函数设计 在面对大型项目的时候,编程人员不可避免地需要编写越来越多的代码。在实际编 码过程中,人们往往会发现有很多功能相同的代码片段被反复地重用和执行。因此,人们 开始考虑是否可以将这些功能明确且被经常使用的代码片段从程序中抽离出来单独封 装。于是,函数(Function)的概念出现在了编程语言里。有了函数的帮助,我们便可以更 好地组织和规划更加大型的项目。 在函数的设计方面,我们可以向函数提供必要的参数作为输入,同时也可以从函数获 取所需要的返回值。Python采用def这个关键字来定义一个函数。代码3.22用def定 义了一个函数,名称为foo,并且foo()函数的参数为x,返回值(return)为x**2。 代码3.22 Python函数定义和执行样例 In[*]: def foo(x): """ 这是一个计算二次方的函数 """ 第3 章 Python 编程基础 57 return x ** 2 if _ _name_ _ =='_ _main_ _': print(foo(8.0)) ..Ou..t[..*..]:..6..4...0 .................................................................... 3.7 Python 面向对象编程 Python从设计之初就已经是一门面向对象的编程语言。与C++、Java等高级编程语 言一样,使用Python创建一个类或者实例化一个对象,是很容易的操作。 我们首先要了解一些面向对象语言所包含的基本概念。 ● 类(Class)。类是用来描述具有相同属性和方法的对象的集合。类是我们在日常 生活中用来描述事物的抽象概念,例如猫、狗、学生、雇员等,都可以用来概括描述 一类事物。为了更进一步描述类,我们通常需要在类中定义必要的数据成员和方 法(函数)。 ● 对象(Object)/实例(Instance)。对象/实例是通过类具象化定义的数据结构。例 如,我们定义“范淼”是一位“学生”,所以,“学生”类的一个对象或者具体实例是“范 淼”。而创建一个类的实例,即创建类的具体对象的过程称为实例化。沿用之前的 例子,创建“范淼”是对“学生”概念的实例化过程。 ● 数据成员。数据成员用来定义类的相关数据,包括类变量、实例变量(属性)等。例 如,对于“学生”这个类,通常我们需要记录学生的姓名、年龄、性别等属性 (Attribute),同时,这些属性会根据具体对象/实例的不同而存储不同的数值。 ● 方法(Method)。方法是类里面所定义的函数。例如,“学生”这个类可以有入学、 分班、上课、考试等方法,这些方法可以对每个对象自身的属性,或者结合其外部信 息,给出必要的反馈。 接下来,我们通过一个有关学生信息处理的样例代码来具体说明上述有关Python面 向对象编程的基本概念。代码3.23中定义了一个名为Student的类。 代码3.23 Python面向对象编程样例 In[*]: class Student: count=0 _ _tax_discount_rate=0.1 58 Python 机器学习及实践——从零开始通往Kaggle 竞赛之路(2022 年度版) def _ _init_ _(self, name, age, sex, fee, is_married): self.name=name self.age=age self.sex=sex self._ _fee=fee self._ _is_married=is_married Student.count +=1 def display_student(self): print("姓名: %s, 年龄: %d, 性别: %s" %(self.name, self.age, self .sex)) def display_fee(self): print("%s 的学费为%f" %(self.name, self._ _fee)) def _ _get_is_single(self): if self._ _is_married: return False else: return True def get_tax_return(self): if self._ _get_is_single(): return self._ _fee * Student._ _tax_discount_rate else: return 0.0 def display_tax_return(self): print("%s 的退税额度为:%f" %(self.name, self.get_tax_return())) 第3 章 Python 编程基础 59 if _ _name_ _ =='_ _main_ _': student_1 =Student("范淼", 29, "男", 5000.0, False) student_2 =Student("刘晓龙", 34, "男", 5500.0, False) student_1.display_student() student_2.display_student() print("目前学生总数为%d 人" %Student.count) student_3 =Student("孙华枭", 28, "男", 5600, True) student_4 =Student("陈蓓", 27, "女", 4500, True) print("目前学生总数为%d 人" %Student.count) student_1.display_tax_return() student_3.display_tax_return() Out[*]: 姓名: 范淼, 年龄: 29, 性别: 男 姓名: 刘晓龙, 年龄: 34, 性别: 男 目前学生总数为2 人 目前学生总数为4 人 范淼的退税额度为:500.000000 孙华枭的退税额度为:0.000000 .................................................................................. Student类中包含了公开的属性name、age、sex,以及私有的属性__fee和__is_ married。Student类中也定义了公开的方法display_student()、display_fee()、get_tax_ return()和display_tax_return(),以及私有的方法__get_is_single()。 从上述属性和方法的命名规则,我们可以看出,如果想要私有化属性或者方法,需要 在属性和方法的前面增加双下画线“__”。 此外,我们还注意到Student类中有两个特别的地方:一个是__init__()方法,这是初 始化对象或者实例时需要默认调用的方法,所有的公有和私有属性都在这个方法中初始 化;另一个是在__init__()方法外侧的count公有变量和__tax_discount_rate私有变量, 这两个变量的值会在Student类的所有实例(对象)之间共享。 最后,需要强调的是,每一个类的方法在声明时,至少要引入self参数代表这个类本 身,然后再声明其他的函数参数。 60Python机器学习及实践——从零开始通往Kaggle竞赛之路(2022年度版) 3.8 Python 编程库(包)导入 当各位读者已经学会如何通过封装和调用自己编写的函数来完成较为复杂的任务 时,心中一定充满了成就感。特别是如果对于自己所编写的某些函数的功能和效率都信 心十足,读者一定非常希望可以和其他人分享,并且也期望别人的程序重用这些函数模 块。这种分享的动机激励着Python开发者互通有无,使得第三方编程库(Library)或者 包(Package)的概念应运而生。有一些编程库默认配置在Python的解释器环境中,这些 是我们经常要用到的;也有一些是由其他编程爱好者所开发的,发布在其他平台上。我们 可以借助AnacondaNavigator(如图3.或者cond如图3.命令为 6所示)a命令(7所示, condainstalmatplotlib)安装这些编程库。 图3.使用Aaodaiaor在虚拟环境pto_ev中安装mapolb编程库 6 ncnaNvgtyhnntlti 事实上,越是复杂的大型项目越不可能从零开始编程,更不可能要求一位程序员自行 编写一个大型项目所有功能的代码。实际使用中,哪怕是执行一些相对简单的数学运算, 我们甚至都能在Pyn语言的内置编程库(包)中找到可以导入(t)的编程库。代 码3. thothon编程库( 的方法。 impor 24列出了几种导入Py包)