# Python基础课程 ## 1. Python介绍与安装 ### 1.1 Python介绍 - #### 1.1.1 面向对象概述 Python是一种面向对象的计算机程序设计语言,而面向对象(Object Oriented)是一种软件开发方式,是一种编程范式。面向对象是相对于面向过程(Procedure Oriented)来讲的,两者的编程思想如下: | **软件开发方式** | **编程思想** | |:--:|:--:| | 面向过程(Procedure Oriented) | 以过程为中心,分析解决问题的步骤,并用函数依次实现步骤。 | | 面向对象(Object Oriented) | 以对象为中心,把构成问题的事物分解为各个对象,描述某个对象在整体解决方案中的行为。 | 为了更通俗易懂地解释两者的差异,此处以五子棋游戏为例。 面向过程的设计思路如下: (1) 分析解决方法,将其分为九个步骤:开始游戏、落黑子、绘制画面、判断输赢、落白子、绘制画面、判断输赢、返回步骤、输出结果; (2) 用函数依次实现上述步骤,并在主函数内依次调用各个步骤的函数。 而面向对象的设计思路如下: (1) 将五子棋游戏分为3个对象:黑白双方、棋盘系统(负责绘制画面)、规则系统(负责判断输赢); (2) 为所有对象赋予属性、行为。第一类对象(黑白双方)负责接受用户输入,并将棋子布局的变化告知第二类对象(棋盘系统)。第二类对象(棋盘系统)接收变化信息后,将其显示于屏幕,同时利用第三类对象(规则系统)对棋局进行判定。 - #### 1.1.2 Python概述 Python是一种跨平台的计算机程序设计语言,它的第一个公开发行版发布于1991年。"Python"这个名字源于创始人Guido van Rossum喜欢的戏剧团体Monty Python。 Python提供了丰富的API(Application Programming Interface,应用程序接口)和工具,程序员能够轻松地使用C语言、C++、Cython来编写扩充模块。除此之外,Python编译器本身也可以被集成到其它需要脚本语言的程序内,所以Python常被用于集成与封装其它语言编写的程序。 Python的语法、动态类型和其解释型语言的本质,使它成为多数平台上写脚本和快速开发应用的编程语言。随着版本的不断更新和语言新功能的添加,Python逐渐被用于独立的、大型项目的开发。 :::{Note} Python2.0版本自2020年起已停止维护,因此建议使用Python3.0及以上版本。 ::: - #### 1.1.3 Python特点 (1) 易于学习:Python有相对较少的关键字,结构简单,语法定义明确。 (2) 易于阅读、维护:Python代码定义清晰,源代码容易维护。 (3) 运行速度快:Python的底层与很多标准库、第三方库是用C语言写的,运行速度非常快。 (4) 免费、开源。 (5) 丰富的库:Python具备庞大的标准库,可用于处理各种工作,包括正则表达式、文档生成、单元测试、线程、数据库、网页浏览器、CGI、FTP和其他与系统有关的操作。 (6) 可移植:由于Python的开源本质,它已经被移植在许多平台上,如Linux、Windows等。 ### 1.2 查看Python :::{Note} 本套Python教程的操作是基于系统Ubuntu18.04所进行的,该系统自带Python3.6.9。为避免在后续学习过程中因版本差异出现问题,建议用户保留Python3.6.9版本,对本节内容仅做了解即可。 ::: 输入指令"**python3 -V**",并按下回车,即可查看当前的Python版本。 ```bash python3 -V ``` ### 1.3 PyCharm安装方法 为了方便学习python语言,本节会对PyCharm编辑器的安装进行教学。 - #### 1.3.1 下载PyCharm (1) 输入指令"**sudo apt install snapd snapd-xdg-open**"安装snap 安装包格式。 ```bash sudo apt install snapd snapd-xdg-open ``` (2) 输入指令"**snap refresh**"刷新snap。 ```bash snap refresh ``` :::{Note} 如果下面的错误无法连接进行刷新,可以更换其他的源,例如清华源再进行刷新。 ::: (3) 输入指令"**sudo snap install pycharm-community --classic**"安装PyCharm。 ```bash sudo snap install pycharm-community --classic ``` - #### 1.3.2 打开PyCharm (1) 我们打开"**菜单**"点击PyCharm。 (2) 创建并配置PyCharm工程。点击New Project新建PyCharm工程。 (3) 选择 Previously configured interpreter并点击 (4) 选择System lnterprefter。 (5) 点击"create"。 (6) 最后进入下图界面,即完成。 - #### 1.3.3 汉化PyCharm (1) 点击"**file**"。 (2) 点击"**settings**"。 (3) 选择Plugins,并在搜索栏内输入chinese,然后安装前面图中两个包。 (4) 若在安装时遇到图中提示,点击"**accept**"。 (5) 点击"**Restart IDE**"。 (6) 重启PyCharm后完成汉化。 - #### 1.3.4 PyCharm的基本介绍和基本使用方法 (1) 界面基本布局如下图: (3) 点击新建,选着python文件。 (4) 然后给你新建的python文件命名。 (5) 最后结果如下图: (6) 右键代码区我们可以选择运行,在输出终端可以到输出的结果。 想要了解更多PyCharm的使用,请访问PyCharm官:https://www.jetbrains.com/zh-cn/pycharm/。 ## 2. 第一个程序 字符串即多个字符的集合,由双引号或单引号包围。字符串内可包含英文字母、阿拉伯数字、汉字以及各种符号。 本节会讲解一个简单、常用的Python程序——在屏幕打印字符串"**Hello World**"。 ### 2.1 操作步骤 ```bash sudo apt-get install vim ``` (1) 若出现是否继续执行的相关提示,输入"**Y**",并按下回车。若安装过程中没有出现报错,则安装成功。 (2) 输入指令"**mkdir test**",并按下回车,在当前目录新建一个名为"**test**"的文件夹。 ```bash mkdir test ``` (3) 输入指令"**cd test/**",并按下回车,进入"**test**"文件夹。 ```bash cd test/ ``` (4) 输入指令"**sudo apt install vim**",并按下回车,新建一个名为"**hello**"的程序文件。 ```bash sudo apt install vim ``` (5) 输入指令"**touch hello.py**",并按下回车,新建一个名为"**hello**"的程序文件。 ```bash touch hello.py ``` (6) 输入指令"**vim hello.py**",并按下回车,打开程序文件。 ```bash vim hello.py ``` (7) 按下"**I**"键进入编辑模式,并输入代码"**print("Hello World")**"。 (8) 按下"**Esc**"键,输入"**:wq**"并回车,进行保存与退出。 ```bash :wq ``` (9) 输入指令"**python3 hello.py**",并按下回车,运行程序文件,终端界面会打印指定字符串。 ```bash python3 hello.py ``` ### 2.2 拓展内容 除了字符串,print()函数还可以用于输出数学表达式的结果。此处以**在程序文件内添加包含数学表达式的print()函数**为例,具体操作步骤如下: (1) 启动虚拟机,点击系统任务栏的图标,并点击图标,或使用快捷键"**Ctrl+Alt+T**",打开命令行终端。 (2) 输入指令"**cd test/**",并按下回车,进入"**test**"文件夹。 ```bash cd test/ ``` (3) 输入指令"**vim hello.py**",并按下回车,打开程序文件。 ```bash vim hello.py ``` (4) 按下"**I**"键进入编辑模式,并输入代码"**print(100+100)**"。 :::{Note} 数学表达式两端无需添加双引号。 ::: (5) 按下"**Esc**"键,输入"**:wq**"并回车,进行保存与退出。 ```bash :wq ``` (6) 输入指令"**python3 hello.py**",并按下回车,运行程序文件,终端界面会打印数学表达式的计算结果。 ```bash python3 hello.py ``` ### 2.3 函数说明 print()函数用于打印输出,语法格式如下: ```python print(*objects, sep='', end='\n', file=sys.stdout, flush=False) ``` 第一个参数"**objects**"是输出对象。一次输出多个对象时,对象之间需用逗号"**,**"分隔; 第二个参数"**sep**"用于在输出对象之间插入字符串,默认值为一个空格符; 第三个参数"**end**"用于在输出结尾添加字符串,默认值为一个换行符; 第四个参数"**file**"是写入的文件对象,默认值为系统标准输出"**sys.stdout**",即屏幕; 第五个参数"**flush**"用于控制输出缓存,默认值为"**False**"。 ## 3. Python基础语法 本节会对Python的基础语法进行讲解说明,如注释、缩进规则、编码规范等。 ### 3.1 注释 注释是对程序的解释和说明。Python支持两种注释类型:单行注释、多行注释。 (1) 单行注释 使用井号键"#"作为单行注释的符号,语法格式如下: ```python # 注释内容 ``` (2) 多行注释 在注释内容的开头与结尾处各自使用三个单引号"**'''**"或三个双引号"**"""**"(单引号和双引号请通过英文输入法下进行),即可对多行内容进行注释,语法格式如下: ```python ''' 注释内容 注释内容 ''' ``` 或者: ```python """ 注释内容 注释内容 """ ``` ### 3.2 缩进规则 Python采用代码缩进和冒号"**:**"来区分代码块之间的层次。 在Python中,对于类定义、函数定义、流程控制语句、异常处理语句等,行尾的冒号和下一行的缩进,代表下一个代码块的开始,而缩进的结束则表示此代码块的结束。 以下图代码为例,每一个红框为一个代码块。 Python对代码的缩进要求非常严格,同一级别代码块的缩进量必须保持一致。在编码时,可以使用"**Tab**"键进行缩进,也可以通过自行输入4个空格进行缩进。 :::{Note} 通常以4个空格为一个缩进单位。默认情况下,一个"Tab"键代表4个空格。 ::: ### 3.3 编码规范 Python采用PEP8作为编码规范。其中,"**PEP**"是指Python增强建议书(Python Enhancement Proposal),而"**8**"是指Python代码的样式指南。 在编码时严格遵守编码规范,能够令代码看起来更整洁、美观,有益于增加代码的可读性。下面是部分编码规则: (1) 一个import导入一个模块,尽量避免一次导入多个模块。 | **推荐做法** | | |:--:|:--:| | **不推荐做法** | | (2) 不在行尾添加分号"**;**",不将两条命令放置在同一行。 | **推荐做法** | | |:--:|:--:| | **不推荐做法** | | (3) 每行的字符数尽量不多于80,可将命令分为多行,并使用小括号"**()**"进行连接。此外,不推荐使用反斜杠"**\\**"连接多行内容。 | **推荐做法** | | |:--:|:--:| | **不推荐做法** | | (4) 使用必要的空行可以增加代码的可读性。 (5) 通常情况下,运算符两侧、函数参数之间以及逗号两侧,都建议使用空格进行分隔。 ### 3.4 标识符命名规范 标识符的主要作用就是作为变量、函数、类、模块以及其他对象的名称。在Python中,标识符的命名需要遵守一定的命令规则,例如: (1) 标识符由字符(A~Z、a~z)、下划线"**\_**"和数字组成,但不能使用数字作为第一个字符。 (2) 标识符不能和Python中的关键字/保留字相同,可以查看下面的"**5.关键字/保留字**"的相关介绍。 (3) 标识符中不能包含空格、"**@**"、"**%**"和"**\$**"等特殊字符。 结合上述三点规则,下表列举了部分命名合法的标识符与不合法的标识符: | **命名合法的标识符** | | |:--:|:--:| | **命名不合法的标识符** | | (4) 标识符中的字母是严格区分大小写的。以"**num**"、"**Num**"和"**NUM**"为例,这三个变量是完全独立、毫无关联的。 (5) 以下划线"\_"为开头的标识符具备特殊含义,除非特定场景需要,应避免使用以下划线开头的标识符。 | **标识符** | **含义** | **例子** | |:--:|:--:|:--:| | 以单下划线开头 | 不能直接访问的类属性,其无法通过"from...import\*"的方式导入 | \_width | | 以双下划线开头 | 类的私有成员 | \_\_add | | 以双下划线作为开头和结尾 | 专用标识符 | \_\_init\_\_ | (6) Python支持使用汉字作为标识符,但为了避免出现奇怪错误,应尽量避免如此命名标识符。 除了上述规则,在不同场景下,标识符的命名也有对应的规范需要注意,例如: ① 用作模块名时,应尽量短小,且全部使用小写字母,可以使用下划线进行分割,如"game_mian"、"game_register"。 ② 用作包的名称时,应尽量短小,全部使用小写字母,如"com.mr"、"com.mr.book",不推荐使用下划线。 ③ 用作类名时,应采用单词首字母大写的形式。如"Book"定义一个图书类。 ④ 用作模块内部的类名时,可采用"下划线+首字母大写"的形式,如"\_Book"。 ⑤ 用作函数名、类中的属性名和方法名时,应全部使用小写字母,多个单词之间可以用下划线进行分割。 ⑥ 用作常量的名称时,应全部使用大写字母,单词之间可以用下划线进行分割。 ### 3.5 关键字/保留字 保留字,也可称作关键字,是Python语言中一些已经被赋予特定意义的单词。在编程时,不能将这些保留字作为标识符给变量、函数、类、模板或其他对象命名。 在Python交互式编程环境内可以查看Python的保留字,具体操作步骤如下: (1) 打开虚拟机,启动系统。点击系统任务栏的图标,并点击图标,或使用快捷键"**Ctrl+Alt+T**",打开命令行终端。 (2) 输入指令"**python3**",并按下回车,进入Python交互式编程环境。 ```bash python3 ``` (3) 输入指令"**import keyword**",并按下回车,导入模块"**keyword**"。 ```bash import keyword ``` (4) 输入指令"**keyword.kwlist**",并按下回车,即可查看Python的所有保留字。 ```bash keyword.kwlist ``` (5) 输入指令"**exit()**",并按下回车,即可退出Python交互式编程环境。 ```bash exit() ``` :::{Note} Python严格区分大小写的规则同样适用于保留字,即"if"是保留字,但"IF"、"iF"和"If"不是保留字。 ::: - #### 3.5.1 数据类型 Python3中的数据类型分为六大类:数字(Number)、字符串(String)、列表(List)、元组(Tuple)、字典(Dictionary)和集合(Set)。 其中,数字(Number)、字符串(String)和元组(Tuple)是不可变数据,而列表(List)、字典(Dictionary)和集合(Set)是可变数据。 :::{Note} 在Python中,可以利用type()函数查看变量的类型。 ::: **(1) 数字(Number)** 表示数字或数值的数据类型称为数字类型。数字类型包含以下四种: ① 整型(int):表现形式有二进制、八进制、十进制和十六进制。 ② 浮点型(float):一般以十进制表示,由整数和小数组成。每个浮点型数据占8个字节,即64位。 ③ 复数类型(complex):由实部和虚部组成,实部部分和虚部部分都是浮点型。 ④ 布尔类型(bool):仅有"**True**"和"**False**"两个取值,"**True**"对应整数"**1**","**False**"对应整数"**0**"。 **(2) 字符串(String)** 一个字符串就是若干个字符的集合。在Python语言中,字符串的表示方法有三种: ① 单引号 ```python ' ``` ② 双引号 ```python " ``` ③ 三重引号 ```python ''' ``` 其中,用单引号和双引号表示的字符串是等价的,且返回对象的类型相同。 :::{Note} 当字符串内出现引号,需要对其进行转义处理,即在引号前添加反斜杠"\\,以免出现语法错误。 ::: **(3) 列表(List)** 列表是Python中的一种序列结构,可以存储任意类型的数据,如整数、小数、字符串、列表、元组等,其创建格式如下: ```python 变量名 = [元素1, 元素2,..., 元素n] ``` 列表不限制元素个数,且同一列表内可包含不同数据类型的元素。但为了程序的可读性,建议一个列表内只存放一种类型的数据。 列表的每一个元素都对应一个整数型的索引值,可以通过索引值来得到相应的元素值,进而对其进行修改与删除。 **(4) 元组(Tuple)** 元组是Python中另一种重要的序列结构,和列表类似,其创建格式如下: ```python 变量名 = (元素1, 元素2,..., 元素n) ``` 与列表不同,元组是不可变序列,不支持修改或删除元素值。此外,元组内只包含一个元素时,需要在元素后面添加逗号,否则括号会被当作运算符使用。 **(5) 字典(Dictionary)** 字典是一种无序的、可变的序列,其创建格式如下: ```python 变量名 = (key1:value1, key2:value2,…, keyn:valuen) ``` 字典是Python中唯一的映射类型,即元素之间存在相互对应的关系。一般将各个元素对应的索引称为"**键(key)**",各个键对应的元素称为"**值(value)**",键与其关联的值称为"**键值对**"。 字典的元素可以是列表、元组、字典等任意数据类型,但键(key)值必须使用不可变类型。此外,在同一个字典变量中,键(key)值必须是唯一的。 **(6) 集合(Set)** 集合用于存储不重复的元素,其创建格式如下: ```python 变量名 = {元素1, 元素2,..., 元素n} ``` 集合只能存储不可变的数据类型,如整形、浮点型、字符串、元组,而无法存储列表、字典、集合这些可变的数据类型。 ## 4. Python条件语句 本节会对Python的条件语句进行介绍说明,并通过结合相关例程加深理解。 ### 4.1 条件语句介绍 条件语句,即通过判断条件是否成立,根据条件表达式的结果,控制不同代码块的执行。 ### 4.2 条件表达式 条件表达式由运算符和操作数组成,以"**a\<4**"为例,其中,"**a**"和"**4**"都为操作数,"**\<**"为运算符。 判断条件可以是具有布尔属性的任意元素,包括数据、变量、由变量与运算符组成的表达式。若其布尔属性为"**True**",条件成立;若为"**False**",则条件不成立。 条件表达式常用的运算符如下表所示:
分类运算符数学符号操作符含义
算术运算符++加法
--减法
*×乘法
/÷除法,结果为浮点数
// 除法,结果为向下取整的整数
%%取模/求余
**^幂运算
关系运算符===等于
!=不等于
>>大于
<<小于
>=>=大于或等于
<=<=小于或等于
成员运算符in存在/属于
not in不存在/不属于
Python支持通过保留字"**not**"、"**and**"和"**or**"对判断条件进行逻辑组合。 (1) not:表示单个条件的"**否**"关系。若"**条件**"的布尔属性为"**True**",则"**not 条件**"的布尔属性为"**False**";若"条件"的布尔属性为"**False**",则"**not 条件**"的布尔属性为"**True**"。 (2) and:表示多个条件之间的"**与**"关系。当且仅当使用and连接的所有条件的布尔属性都为"**True**"时,逻辑表达式的布尔属性为"**True**",否则为"**False**"。 (3) or:表示多个条件之间的"**或**"关系。当且仅当使用or连接的所有条件的布尔属性都是"**False**"时,逻辑表达式的布尔属性为"**False**",否则为"**True**"。 ### 4.3 选择结构 条件语句可分为三种形式:单分支选择结构、双分支选择结构和多分支选择结构。 - #### 4.3.1单分支选择结构 单分支选择结构的语法格式和执行流程如下: | **语法格式** | **执行流程** | |:--:|:--:| | | | 若if语句中的判断条件成立,则依次执行代码块1和代码块2;否则,直接跳过if语句后的代码块1,执行代码块2。 - #### 4.3.2 双分支选择结构 双分支选择结构的语法格式和执行流程如下: | **语法格式** | **执行流程** | |:--:|:--:| | | | 若if语句中的判断条件成立,则执行代码块1;若判断条件不成立,则执行代码块2。 - #### 4.2.3 多分支选择结构 多分支选择结构的语法格式和执行流程如下: | **语法格式** | **执行流程** | |:--:|:--:| | | | (1) 若if语句中的判断条件1成立,则执行代码块1。 (2) 若判断条件1不成立,则依次对elif语句中的判断条件进行判断,当出现成立的判断条件,则执行该条件对应的代码块。 (3) 若if语句和elif语句中的判断条件皆不成立,则执行代码块n+1。 ### 4.4 实验步骤 本节例程会**根据输入的身高、体重,计算对应的BMI值,并进行健康评估**。 开始操作前,需要先将目录"**第3章 Python编程语言-\>Python基础及进阶学习-\>第4课 Python条件语句-\>例程源码**"下的例程"**conditional_statement.py**"复制到共享文件夹。 关于共享文件夹的配置方法,可参考目录"**第2章 Linux系统简介及使用入门-\>Linux基础课程-\>第3课 Linux系统安装及换源方法**"下的文档。 :::{Note} 输入指令时需严格区分大小写,且可以使用"Tab"键补齐关键字。 ::: (1) 启动虚拟机,点击系统任务栏的图标,并点击图标,或使用快捷键"**Ctrl+Alt+T**",打开命令行终端。 (2) 输入指令"**cd /mnt/hgfs/Share/**",并按下回车,进入共享文件夹。 ```bash cd /mnt/hgfs/Share/ ``` (3) 输入指令"**python3 conditional_statement.py**",并按下回车,运行例程。 ```bash python3 conditional_statement.py ``` ### 4.5 实验效果 依次输入身高和体重,并按下回车,终端处会打印对应的BMI指数和评估结果。 ### 4.6 程序分析 可以在目录"**[OpenCV计算机视觉学习-\>图像处理进阶篇-\>第5课 图像处理——形态学处理-\>例程源码]()**"下查看例程"**conditional_statement.py**"。 ```python height = float(input("height(m):")) weight = float(input("weight(kg):")) bmi = weight/(height ** 2) # 计算BMI指数 print("BMI: " + str(bmi)) if bmi < 18.5: print("体重过轻") elif bmi >= 18.5 and bmi < 24.9: print("正常范围,注意保持") elif bmi >= 24.9 and bmi < 29.9: print("体重过重") else: print("肥胖") ``` **(1) 数据输入** 通过调用input()函数来接收输入数据,函数括号内为提示信息。 ```python height = float(input("height(m):")) weight = float(input("weight(kg):")) ``` **(2) 数据计算** 根据BMI指数的计算公式,对输入数值进行处理,并通过print()函数将计算结果打印至终端界面。 ```python bmi = weight/(height ** 2) # 计算BMI指数 print("BMI: " + str(bmi)) ``` print()函数的语法格式如下: ```python print(\*objects, sep=’ ’, end=’\n’, file=sys.stdout, flush=False) ``` 第一个参数"**objects**"是输出对象。一次输出多个对象时,对象之间需要用逗号"**,**"分隔; 第二个参数"**sep**"用于在输出对象之间插入字符串,默认值为一个空格符; 第三个参数"**end**"用于在输出结尾添加字符串,默认值为一个换行符; 第四个参数"**file**"是写入的文件对象,默认值为系统标准输出"**sys.stdout**",即屏幕; 第五个参数"**flush**"用于控制输出缓存,默认值为"**False**"。 **(3) 范围判断** 由于判别结果多于两个,此处需要采用多分支选择结构,即if-elif-else语句。 ```python if bmi < 18.5: print("体重过轻") elif bmi >= 18.5 and bmi < 24.9: print("正常范围,注意保持") elif bmi >= 24.9 and bmi < 29.9: print("体重过重") else: print("肥胖") ``` ① 当BMI指数小于18.5,打印评估结果"**体重过轻**"; ② 当BMI指数大于或等于18.5,且小于24.9,打印评估结果"**正常范围,注意保持**"; ③ 当BMI指数大于或等于24.9,且小于29.9,打印评估结果"**体重过重**"; ④ 当BMI指数大于或等于29.9,打印评估结果"**肥胖**"。 ## 5. Python循环语句 在程序设计中,算法的某些操作步骤在一定的条件下会被重复执行,这就是循环结构。本节会对Python的循环语句进行介绍说明,并通过结合相关例程加深理解。 ### 5.1 循环语句介绍 循环语句包含"**while**"和"**for**",可以用于重复进行某些操作。 - #### 5.1.1 while循环 while循环的语法格式和执行流程如下: | **语法格式** | **执行流程** | |:--:|:--:| | | | 当循环条件为"**True**",则循环执行while循环中的代码块,直至循环条件为"**False**",循环结束。条件持续为"**True**"的while循环被称为"**死循环**"。 - #### 5.1.2 for循环 for循环的语法格式和执行流程如下: | **语法格式** | **执行流程** | |:--:|:--:| | | | "**目标**"可以是字符串、列表、元组、字典等序列类型,而"**循环变量**"用于存放从序列类型变量中读取到的元素。 进入for循环后,遍历目标内的元素,执行for循环内的代码块,直至遍历完成,循环结束。 ### 5.2 循环控制语句介绍 当需要中断循环,或跳过本次循环,执行下一次循环,循环控制语句便可派上用场。循环控制语句包含"**break**"、"**continue**"和"**pass**"。 - #### 5.2.1 break语句 break语句用于跳出整个循环,其语法格式和执行流程如下: | **语法格式** | **执行流程** | |:--:|:--:| | | | | | | 当执行到判断条件语句,若判断条件为"**True**",则跳出整个循环;若判断条件为"**False**",则继续执行代码块2,继续循环。 - #### 5.2.2 continue语句 continue语句用于跳出本次循环,继续执行下次循环,其语法格式和执行流程如下: | **语法格式** | **执行流程** | |:--:|:--:| | | | | | | 当执行到判断条件语句,若判断条件为"**True**",则直接结束本次循环,进入新一轮循环;若判断条件为"**False**",则继续执行代码块2,完成本次循环。 - #### 5.2.3 pass语句 pass语句即为空语句,不执行任何动作,用于保持程序结构的完整性。 ### 5.3 实验步骤 本节例程会**计算输入整数的阶乘,并打印输入字符串的各个元素**。 开始操作前,需要先将目录"**第3章 Python编程语言-\>Python基础及进阶学习-\>第5课 Python循环语句-\>例程源码**"下的例程"**loop_statement.py**"复制到共享文件夹。 关于共享文件夹的配置方法,可参考目录"**第2章 Linux系统简介及使用入门-\>Linux基础课程-\>第3课 Linux系统安装及换源方法**"下的文档。 ```bash 输入指令时需严格区分大小写,且可以使用"Tab"键补齐关键字。 ``` (1) 启动虚拟机,点击系统任务栏的图标,并点击图标,或使用快捷键"**Ctrl+Alt+T**",打开命令行终端。 (2) 输入指令"**cd /mnt/hgfs/Share/**",并按下回车,进入共享文件夹。 ```bash cd /mnt/hgfs/Share/c ``` (3) 输入指令"**python3 loop_statement.py**",并按下回车,运行例程。 ```bash python3 loop_statement.py ``` ### 5.4 实验效果 输入一个整数,并按下回车,终端处会打印该数的阶乘。 输入一个字符串,并按下回车,终端处会打印该字符串的各个元素。 ### 5.5 程序分析 可以在目录**第3章 Python编程语言-\>Python基础及进阶学习-\>第5课 Python循环语句-\>例程源码**"下查看例程"**loop_statement.py**"。 ```python n = int(input("请输入一个整数:")) fact = 1 i = 1 while i <= n: fact = fact * i i = i + 1 print("n!={}".format(fact)) string = input("请输入一个字符串:") for c in string: print(c) ``` ### 5.6 计算数值的阶乘 **5.6.1 数据输入** 通过调用iuput()函数来接收输入数据,函数括号内为提示信息。 ```python n = int(input("请输入一个整数:")) ``` **5.6.2 变量创建** 创建两个变量,用于后续的计算。其中,"**fact**"用于存储当前阶乘值。 ```python fact = 1 i = 1 ``` **5.6.3 while循环** 利用while循环语句计算指定整数的阶乘。循环过程中,"**i**"值不断累加,当该值大于输入的整数时,循环结束。随后,通过调用print()函数,将计算结果打印至终端界面。 ```python while i <= n: fact = fact * i i = i + 1 print("n!={}".format(fact)) ``` print()函数的语法格式如下: ```python print(\*objects, sep=’ ’, end=’\n’, file=sys.stdout, flush=False) ``` 第一个参数"**objects**"是输出对象。一次输出多个对象时,对象之间需用逗号"**,**"分隔; 第二个参数"**sep**"用于在输出对象之间插入字符串,默认值为一个空格符; 第三个参数"**end**"用于在输出结尾添加字符串,默认值为一个换行符; 第四个参数"**file**"是写入的文件对象,默认值为系统标准输出"**sys.stdout**",即屏幕; 第五个参数"**flush**"用于控制输出缓存,默认值为"**False**"。 ### 5.7 打印字符串元素 **5.7.1 数据输入** 通过调用iuput()函数来接收输入数据,函数括号内为提示信息。 ```python string = input("请输入一个字符串:") ``` **5.7.2 for循环** 利用for循环语句即可依次获取输入字符串的各个元素。随后,通过在循环结构内调用print()函数,便可实现输入字符串的拆分打印。 ```python for c in string: print(c) ``` ## 6. Python函数和模块 本节会对Python的函数和模块进行介绍说明,并通过结合相关例程加深理解。 ### 6.1 函数介绍 在Python语言中,函数可分为内置函数和自定义函数。 内置函数也称作内建函数,是Python自带的函数,无需导入任何函数库即可直接调用。常用的内置函数有print()、input()、range()等。 自定义函数就是将一段有规律的、可重复使用的代码定义成函数,以提升代码的复用率和可维护性。 ### 6.2 函数定义 在Python语言中,函数通常是由函数名、参数列表以及一系列语句组成的函数体构成的。函数定义的一般格式如下: ```python def 函数名(参数列表): 函数体 ``` (1) 函数代码块以关键字"**def**"开头,后接函数标识符名称和形参列表; (2) 为方便后期维护,函数标识符名称最好能够体现出函数的功能; (3) 参数列表用于设置该函数可接收的参数,多个参数之间用逗号"**,**"分隔; (4) 任何传入的参数和自变量必须放在括号"**()**"内; (5) 函数内容以冒号"**:**"起始,且严格统一缩进; (6) 函数的第一行语句可选择性地使用文档字符串,即函数说明; (7) 函数都有返回值,默认返回"**None**"。 :::{Note} 创建函数时,即使函数不包含任何参数,函数名后面的小括号"()"仍需保留。 ::: ### 6.3 形参和实参 在编程语言中,函数定义时采用形参,调用时采用实参。两者的功能是数据传送。 **6.3.1 形参(parameter)** 形参,即形式参数,不是实际存在的变量,因此又称虚拟变量。形参是在定义函数名和函数体时使用的参数,用于接收调用该函数时传入的参数,其作用域一般仅限函数体内部。 **6.3.2 实参(argument)** 实参,即实际参数,是在调用时传递给函数的参数,可以是常量、变量、表达式、函数等,其作用域根据实际设置而定。 无论何种类型的实参,在进行函数调用时,它们都必须具有确定的值,以便把这些值传送给形参。 以下图代码为例,函数area()定义处的"**width**"和"**height**"是形式参数,而函数体外定义的变量"**w**"和"**h**"则是实际参数。 ```python # 计算矩形面积的函数area() def area(width,height): return width * height #调用area函数 w = 4 h = 9 print("width=",w,"height=",h,"area=",area(w,h)) ``` 将实参"**w**"和"**h**"传入函数体后,相应的值就被赋予形参"**width**"和"**height**"。形参"**width**"和"**height**"的作用域只限于area()函数体内,而实参"**w**"和"**h**"的作用域则根据外部调用处的设置而定。 ### 6.4 函数返回值 在函数执行完成后,系统根据函数的具体定义,将某些值反馈至外部调用者,该值则称为函数的返回值。 在Python语言中,当函数运行到return语句,即表示函数执行完毕,会返回指定值。若函数内部没有return语句,则函数默认返回"**None**"。 以下图代码为例,调用add()函数后,该函数返回"**x+y**"的运算结果,并将值赋予变量"**result**"。 ```python # 函数定义 def add(x,y): print('x+y=',x+y) return x+y #函数调用 result = add(y=1,x=2) print(result) ``` 需要注意的是,在Python语言中,函数可拥有多个返回值,以下图代码为例: ```python # 函数定义 def calculate(x,y): print('x+y=',x+y) print('x*y=',x*y) return x + y,x * y #函数调用 a,b = calculate(y=1,x=2) print(a,b) ``` calculate()函数内有两个返回值,分别是"**x+y**"和"**x\*y**",调用该函数后,两个返回值分别赋予变量"**a**"和变量"**b**"。 ### 6.5 函数传递 函数参数分为可变类型和不可变类型,两者的调用结果是不同的。 - #### 6.5.1 可变类型 可变类型的调用类似C++的引用传递。如果传递的参数是可变类型,如列表、字典等,函数内部对传入参数的修改会影响到外部变量。 以下图代码为例,change_int()函数内部对传入的列表"**list_01**"进行修改后,外部的变量也会被更改。change_int()函数内的"**append**"作用为向列表内添加元素,这里我们将列表"**\[1,2,3\]**"作为元素添加到列表list_01。 ```python def change_int(list_01): list_01.append([1, 2, 3]) # 修改传入的列表 print("函数内修改后的变量:",list_01) list_01 = [10, 20, 30] cjange_int(list_01) print("函数外变量的值:",list_01) ``` - #### 6.5.2 不可变类型 不可变类型的调用类似C++的值传递。如果传递的参数是不可变类型,如整型、字符串、元组等,函数内部对传入参数的修改不会影响到外部变量。 以下图代码为例,变量"**b**"指向int对象"**2**",在传递至unchange_int()函数时,按传值方式复制变量"**b**",即变量"**a**"和变量"**b**"都指向了同一个int对象"**2**"。 然而,当执行"**a = 10**",变量"**a**"指向新生成的int对象"**10**"。因此,外部变量未发生改变,程序打印的数值应为"**2**"。 ```python def unchange_int(a): a = 10 b = 2 unchange_int(b) print(b) ``` ### 6.6 参数类型 - #### 6.6.1 位置参数 调用函数时,每个实参都按照位置顺序关联至对应的形参,这种关联方式即为位置参数。 以下图代码为例,调用describe_student()函数时,需要依次提供姓名和年龄这两个参数,则实参"**Jack**"和"**18**"分别存储至形参"**person_name**"和"**student_age**"中。 ```python def describe_student(person_name,student_age): print("My name is ",person_name) print(person_name + "is " + student_age + "years old") describe_student('Jack', '18') ``` - #### 6.6.2 默认参数 自定义函数时,可以为每个形参指定默认值。调用函数时,若给形参提供了实参,则采用指定实参;否则,采用形参的默认值。 以下图代码为例,将形参"**student_age**"的默认值设定为"**18**"。当调用describe_student()函数时有为形参"**student_age**"提供实参,则采用指定实参,此处为"**20**";否则,采用默认值"**18**"。 ```python def describe_student(person_name,student_age='18'): print("My name is ",person_name) print(person_name + "is " + student_age + "years old") describe_student('Jack', '20') describe_student('Jack') ``` - #### 6.6.3 不定长参数 在Python语言中,函数还可以定义不定长参数,也叫可变参数。在标识符前面添加"**\***"即可将对应参数定义为不定长参数。 以下图代码为例,将参数"**number**"定义为不定长参数后,在调用calculate()函数时,即使传入参数不是列表或元组,函数也可直接使用。 ```python def calculate(*numbers): sum = 0 for n in numbers: sum = sum + n return sum print(calculate(1, 2, 3, 4)) print(calculate()) ``` - #### 6.6.4 关键字参数 关键字参数就是采用"**形参名称-值**"对的方式进行参数传递。通过此方式指定函数实参时,不再需要与形参的位置完全一致,只需确保参数名称正确。 以下图代码为例,在传递参数时,即使调整了参数顺序,函数仍然能够正常输出。 ```python def describe_student(person_name,student_age): print(person_name + "is " + student_age + "years old") describe_student(person_name+'Jack',student_age='18') describe_student(student_age='20',person_name='Mike') ``` - #### 6.6.5 命名关键字参数 当需要限制参数只能按关键字进行传递时,可以采用命名关键字参数。在自定义函数时,用"**\\**"分隔形参,"**\\**"后面的形参即为命名关键字参数。 以下图代码为例,"**\\**"后面的形参"**live_city**"是命名关键字参数。因此,在传递参数时,它必须采用关键字参数的形式,否则程序会出现报错。 ```python def describe_student(person_name, student_age, *, live_city): print("Name: " + person_name) print("Age: " + student_age) print("City: " + live_city) describe student('Jack', '18', live_city='Guangzhou') ``` :::{Note} 在Python语言中,参数的定义需要遵循一定的顺序:位置参数、默认参数、可变参数、命名关键字参数、关键字参数。 ::: ### 6.7 模块介绍 一般情况下,模块(module)就是一个后缀名为"**.py**"的文件。此外,还有其他可作为module的文件类型,如"**.pyo**"、"**.pyc**"、"**.pyd**"、"**.so**"、"**.dll**",但Python初学者暂不需要接触相关内容。 将能够实现某一特定功能的代码封装为一个独立的模块,这样既可以方便其它程序或脚本导入及使用,又可以有效避免函数名和变量名发生冲突。模块的来源有三种: (1) Python内置模块(标准库); (2) 第三方模块; (3) 自定义模块。 当需要调用某个模块的函数,需要先通过import语句导入该模块后,再对函数进行调用。常用的导入方法有两种(中括号"\[\]"里的内容可省略): (1) import 模块名称\[ as 别名\] 使用这种语法格式的 import 语句,会导入指定模块中的所有成员(包括变量、函数、类等)。当需要使用模块中的成员时,需用该模块名(或别名)作为前缀。 (2) from 模块名称 import 成员名称\[ as 别名\] 使用这种语法格式的 import 语句,只会导入模块中指定的成员,而不是全部成员。同时,当程序中使用该成员时,无需附加任何前缀,直接使用成员名(或别名)即可。 :::{Note} 采用"from 模块名称 import \*"的形式也可以导入指定模块的所有成员,但不推荐此操作。 ::: ## 7. Python容器类型与相关操作 ### 7.1 容器介绍 对象是Python中对数据的抽象,Python程序中的所有数据都是由对象或对象间关系来表示的。Python中,可包含其他对象的引用的对象,称之为"容器"。容器的例子有元组、列表和字典等。这些引用的对象是容器对象值的组成部分。 常用的容器主要划分为两种:序列(如:列表、元组等)和映射(如:字典)。序列中,每个元素都有下标,它们是有序的。映射中,每个元素都有名称(又称"键"),它们是无序的。除了序列和映射之外,还有一种需要注意的容器——"集合"。 ### 7.2 四种容器介绍 - #### 7.2.1 列表 (1) 语法:**\[ 123 , "456" , classObjectA , \[123,"456"\] \]** (2) 特征:列表使用中括号包裹,逗号隔开元素,元素类型任意,可以嵌套,可以用下标进行读写。 (3) 特点:列表元素类型不要求统一,可以对每个元素进行增删改查。可以按照下标删除元素(pop),也可以按照值删除元素(remove),可以插入元素到某个位置(insert),也可以追加元素到列表尾部(append)。 ```python list1 = [123, "123", [123, 456]] ``` - #### 7.2.2 元组 (1) 语法:**(123,456,789,100)**。 (2) 特征:小括号包裹,逗号隔开元素,元素类型必须统一,可以嵌套但是满足类型统一,可以用 下标 进行读,但不可写,更不可增删。 (3) 特点:不可变的列表,所有操作都类似列表,唯一的不同就是只能查,不能增(没有append和insert),删(没有remove和pop),改(不能对元素赋值)。可以认为元组是一个元素类型必须统一且不可修改的列表,只能读里面的内容。 ```python tuple1 = (123, 456, 789) ``` - #### 7.2.3 集合 (1) 语法:{ 1,"23",classObjectA }。 (2) 特征:大括号包裹,逗号隔开元素,元素类型任意,可以嵌套,可以用下标读写。基本和列表一致。 (3) 特点:可以认为是自动除重的列表 ,且不支持排序,其他和列表没区别。 ```python set1 = {123, "123"} ``` - #### 7.2.4 字典 (1) 语法:{"name" :"zhangsan", "age":50} (2) 特征:大括号包裹,逗号隔开元素,元素构成必须统一格式(由分号分隔的两部分,前半部分必须是字符串,后半部分任意),键一定是字符串,如果发现某个元素没包含冒号,则会被当做集合处理。 (3) 特点:最灵活的容器,不支持排序,可以嵌套,通过 \[ \] 和 get 进行元素访问,不可用下标 ,使用 pop 按键进行元素移除(没有remove)。 ```python dict1 = {"123":123, "456":"abc", {"qwe":789}} ``` ### 7.3 容器基本操作 - #### 7.3.1 列表的基本操作
分类关键字/函数/方法说明
增加append()添加元素至尾部
insert()在指定位置插入数据
删除clear()清空列表
pop()默认弹出末尾数据
pop(index)掏出指定所有数据
remove(data)移除指定数据
修改extend(列表2)将列表2的数据追加到列表
查询count(数据)统计数据出现的次数
index(内容)查询内容所在位置
其他copy()将列表复制一份
sort()排序
reverse()逆序列表
(1) append:添加元素到列表尾部。 (2) insert:在指定的位置插入元素,参数中前者为位置,后者为元素。 (3) pop:弹出最后一个元素,也可指定弹出的元素位置。 (4) remove:移除指定的元素。 ```python list1 = [1, 2, 3, 4, 5, 6, 7] list1.append(10) print(list1) list1.insert(2, 3) print(list1) list1.pop(0) print(list1) list1.remove(7) print(list1) ``` (5) index:查询指定元素的位置。 (6) sort:把内容升序排序,也可改为降序排序。 ```python list1 = [1, 7, 3, 8, 5, 9, 4] print(list1.index(4)) list1.sort() print(list1) ``` - #### 7.3.2 元组的基本操作 元组的操作类似列表,主要有以下不同: (1) 元组没有 append()、 extend() 和 insert() 等方法,无法向元组中添加元素。 (2) 元组没有 remove() 或 pop() 方法,也无法对元组元素进行 del 操作,不能从元组中删除元素。 - #### 7.3.3 字典的基本操作
方法用法
get(key,default=None)返回指定键的值,如果值不在字典中返回default值
keys()以列表返回一个字典所有的键
values()以列表返回字典中的所有值
update(dict2)把字典dict2的键/值对更新到dict里
items()以列表返回可遍历的(键,值)元组数据
(1) get:返回指定键的值。 (2) keys:返回字典中所有的键。 (3) values:返回字典中所有的值。 ```python dect1 = {"星期一":1, "星期二":2, "星期三":3, "星期四":4, "星期五":5} print(dict1.get("星期一")) print(dict1.keys()) print(dict1.values()) ``` (4) Update:更新已有的键值对,或添加新的键值对。 (5) items:以列表返回可遍历的键值对元组数组。 ```python dict1 = {"星期一":1, "星期二":2, "星期三":3, "星期四":4, "星期五":5} dict2 = {"星期六":6, "星期天":7} dict1.update(dict2) print(dict1.items()) ``` ## 8. Python类和文件操作 ### 8.1 面向对象 Python是面向对象的高级语言,在Python中一切都是对象。 面向对象是将变量和数据类型绑定到一起,分类进行封装,减少重复代码量。对象是对函数和变量的封装,面向对象的关注点在于谁来做,根据谁来做将一个对象中封装多个方法。 面向对象中有两个核心的概念:**类和对象**。 ### 8.2 类和对象的介绍 - #### 8.2.1 类 类用来描述具有相同的属性和方法的对象集合,是抽象的,类不能直接被使用。它定义了该集合中每个对象所共有的属性和方法,而对象是类的实例。 例如创建一个"猫"类,猫的属性有名字,颜色,年龄等,猫的方法有吃,喝,喵喵叫等,而实例化的对象"橘猫"则会拥有这些定义的属性和方法。 - #### 8.2.2 对象 对象是根据类来创建的一个具体的实例,它具有所属类的属性和方法。在Python中,所有数据类型都被视为对象,也可以自定义对象,自定义对象数据类型就是面向对象中类的概念。 ### 8.3 类的定义 (1) 通过 class 关键字定义,类名通用习惯为首字母大写。 (2) \_init_函数,对类初始化,相当于构造函数,每根据类创建新实例时,Python都会自动运行它。 (3) self函数,隐式形参,对象本身,相当于this函数。 (4) 属性相当于成员变量。 ```python chass Cat(): def __init__(self, name, age): self.name=name self.age=age def eat(self): print("Let's Eat!") def meow(self): print("MEOW~") ``` ### 8.4 实例的创建 (1) 通过类名创建,输入创建所需的属性。 (2) 可以直接调用这些属性和方法。 ```python my_cat = Cat("Tom", "6") print("Name:" + my_cat.name + "Age:" + my_cat.age) my_cat.eat() my_cat.meow() ``` ### 8.5 类的属性与实例属性 (1) 类的\_\_init\_\_下定义的为实例属性,类中\_\_init\_\_外定义的为类属性,类外创建类的实例可以定义属于该实例的属性。 (2) 私有变量:如果有属性不希望被外部访问,我们可以在属性命名时以双下划线开头( \_\_ ),那么该属性就不能使用原变量名访问,即不能从实例调用。 ### 8.6 类的继承和多态 (1) 继承:类的创建时,可以在括号内写上父类的名称,让父类的属性和方法都被继承给子类,若子类没有初始化方法,则会调用父类的初始化方法。 (2) 方法重写:如果在子类中定义的一个方法,其名称、返回类型及参数列表正好与父类中某个方法的名称、返回类型及参数列表相匹配,则为子类的方法重写了父类的方法。 (3) 多态:从一个父类派生出多个子类,可以使子类之间有不同的行为,这种行为称之为多态。更直白的说,就是子类重写父类的方法,使子类具有不同的方法实现 子类与父类拥有同一个方法,子类的方法优先级高于父类,即子类覆盖父类。 ```python class Animal(): def __init__(self, name, age): self.name = name self.age = age def eat(self): print("Let's Eat!") class Cat(Animal): def eat(self): print("Eat Fish!") class Mouse(Animal): def eat(self): print("Eat Cheese") my_cat = Cat("Tom", "6") print("Name:" + my_cat.name + "Age:" + my_cat.age) my_cat.eat() my_mouse = Mouse("Jerry", "5") print("Name:" + my_mouse.name + "Age:" + my_mouse.age) my_mouse.eat() ``` 执行后,子类实例会自动调用父类构造方法,子类会覆盖重写父类同名方法。 ### 8.7 文件的概念及存储方式 计算机中的文件,就是存储在某种长期存储设备上的一段数据,长期存储设备包括:硬盘、U盘、移动硬盘和光盘等等。 在计算机中,文件是以二进制的方式保存在磁盘上的。 文本文件和二进制文件: - 文本文件 - 可以用文本编辑软件查看 - 本质上还是二进制 - 例如:Python源文件 - 二进制文件 - 保存的内容不是给人直接阅读的,而是提供给其他软件使用的 - 例如:图片文件、音频文件、视频文件等等 - 二进制文件不能直接使用文本编辑器查看 ### 8.8 文件夹与文件路径 (1) 文件两个关键属性:"文件名"(通常写成一个单词)和"路径"。 (2) 绝对路径与相对路径:"绝对路径",总是从根文件夹开始。"相对路径",相对于程序的当前工作目录。例如在当前目录下的"test.py"文件,相对路径是"/test.py",绝对路径是"python/scripts/test.py"。 (3) 点(.)和点点(..)文件夹:不是真正的文件夹,而是可以在路径中使用的特殊名称。单个的句点("点")用作文件夹目名称时,是"这个目录"的缩写。两个句点("点点")意思是父文件夹。 ### 8.9 文件读写操作 (1) 打开和关闭文件:调用 open函数传入文件名和标识符,打开文件返回一个File对象,调用 File 对象的 close()方法,可以关闭该文件。也可以使用"with"语句在结束后自动关闭文件。 (2) 文件读取:调用read函数将文件内容读取到对象中,可以使用readline函数每次读取一行,或者readlines函数一次读取所有行,保存在一个列表中。 (3) 文件写入:打开文件时,可加入参数指定:读取模式("r")、写入模式("w")【从开头写】、附加模式("a")【在文件尾开始写】、同时读取和写入文件的模式("r+")。也可以直接用write方法写入。 ```python filename = 'num.txt' with open(filename, 'r+') as file_object: file_object.write("Hiwonder") file_object = open(filename, 'r') lines = file_object.readlines() print(lines[0]) ``` 执行后,会读取刚才写入的第一行数据。 ## 9. Python异常处理 ### 9.1 异常与错误 程序错误是指语法错误(指令输入不正确)和逻辑错误(程序执行结果不正确),而程序异常是一个意外事件,该事件会在程序执行过程中发生,影响了程序的正常执行,比如:打开的文件不存在、被除数为0、操作的数据类型不对、存储错误,互联网请求错误等等。 一般情况下,在Python无法正常处理程序时就会发生一个异常。异常是Python对象,表示一个错误。当Python脚本发生异常时我们需要捕获处理它,否则程序会终止执行。 ### 9.2 常见的异常类 - **NameError**:尝试访问一个没有声明的变量。 - **ZeroDivisionError**:被除数为0。 - **SyntaxError**:语法错误。 - **IndexError**:索引超出序列范围。 - **KeyError**:请求一个不存在的字典关键字。 - **IOError**:输入输出错误。 - **AttributeError**:尝试访问未知的对象属性。 - **ValueError**:传给函数的参数类型部正确。 - #### 9.2.1 异常处理 在代码被解释执行的过程中可能会抛出异常,而异常的处理则采用try....except...的方式。如果try中的代码发生异常,则会跳到expect捕获处理这个异常。 ```python try: print('try...') r = 10 / int('2') print('result:', r) except ValueError as e: print('ValueError:', e) except ZeroDivisionError as e: print('ZeroDivisionError', e) else: print('no error!') finally: print('finelly...') print('END') ``` (1) try代码块为可能发生异常的代码。 (2) except后面是可能发生的异常类型和处理内容。 (3) except可以有多个分支,异常发生匹配到第一个except则退出,如果异常类存在子类和父类,父类异常在前面,则后面的子类异常会无法匹配到。 (4) else语句会在没有发生异常时执行。 (5) finally语句则无论异常有没有发生,都会执行。 ## 10. Python内置函数 ### 10.1 什么是内置函数 Python解释器也是一个程序,它给用户提供了一些常用功能,并给它们起了独一无二的名字,这些常用功能就是内置函数。Python解释器启动以后,内置函数也生效了,可以直接拿来使用。 内置函数是解释器的一部分,它随着解释器的启动而生效;标准库函数是解释器的外部扩展,导入模块以后才能生效。一般来说,内置函数的执行效率要高于标准库函数。 内置函数的数量必须被严格控制,否则 Python 解释器会变得庞大和臃肿。一般来说,只有那些使用频繁或者和语言本身绑定比较紧密的函数,才会被提升为内置函数。例如,在屏幕上输出文本就是使用最频繁的功能之一,所以print()是Python的内置函数。 ### 10.2 内置函数列表
内置函数
abs()delattr()hash()memoryview()set()
all()dict()help()min()setattr()
any()dir()hex()next()slicea()
ascii()divmod()id()boject()sorted()
bin()enumerate()input()oct()staticmethod()
bool()eval()int()open()str()
breakpoint()exec()isinstance()ord()sum()
bytearray()fillter()issubclass()pow()super()
bytes()float()iter()print()tuple()
callable()format()len()property(0type()
chr()frozenset()list()range()vars()
classmethod()getattr()locals()repr()zip()
compile()globals()map()reversed()_import_()
complex()hasattr()max()round()
- #### 10.2.1 运算类型 (1) **abs(x)**:abs函数用来返回一个数值的绝对值,输入的参数x可以是整数浮点数,也可以是复数。 (2) **max(x,key=None)**:max函数的参数x是可迭代对象或者是多个参数,返回其中的最大的元素。max函数可以通过指定关键参数key,来返回最大值。如果有多个最大值时,则返回第一个值。 (3) **min(x,key=None)**:min函数同max函数的用法是一致的,min函数返回的是可迭代对象或者是多个参数中的最小值。 ```python print(abs(-46)) print(max(2, 3, 4, 5)) print(min(2, 3, 4, 5)) ``` (4) **pow(x,y, mod)**:pow函数当只有x和y两个参数时,它的作用是返回x的y次幂,当存在第三个参数mod存在时,pow函数是在x的y次幂基础上对mod进行取余。 (5) **round(number,ndigits)**:返回number舍入到小数点后 ndigits位精度的值。如果ndigits被省略,则返回最接近number的整数。 (6) **sum(x, start=0)**:sum函数是将x中的数值进行从左向右的求和,然后加上start的数值,求和并返回总值。 (7) **divmod(a, b)**:divmod函数将a、b两个数值作为实参,返回a/b的商值和余数。 ```python print(pow(2, 3)) print(round(1.234, 3)) print(sum(1, 2, 3, 4), 2) print(divmod(5, 2)) ``` - #### 10.2.2 转换类型 - **int(x)**:对于输入的数字或者是字符串x,返回x的整数形式,如果x数值为空时,则返回0。 - **float(x)**:对于输入的数字或者是字符串x,返回x的浮点数形式,如果x数值为空时,则返回0.0。 - **complex(real, imag)**:complex函数的返回值为real + imag\*1j的复数形式,或者将字符串或数字转换为复数形式。如果第一个参数real是字符串,那么就不能存在第二个参数。 ```python\ print(int(2.3)) print(float(3)) print(complex(2, 3)) ``` - **bool(x)**:判断参数x是否为真,并返回True或者False。 - **str(x)**:将输入值x转换为字符串类型,并将结果进行返回。 - **bytearray(x, encoding="utf-8")**:bytearray是将输入值x转变为字节组成的有序的可变数组,并将数组进行返回。 - **bytes(x, encoding="utf-8")**:bytes则是将传入的参数x转变为一个不可变的字节数组,并返回该数组。 - **memoryview(x)**:memoryview函数返回的是参数x的内存查看对象,而内存查看对象指的是对支持缓冲区协议的数据,进行包装的一种形式,其返回的对象是元组列表的形式。需要注意的是,传入参数x必须为bytes类型值。 ```python # bool函数 print(bool(3 > 4)) print(bool("2" == "2")) # str函数 print(str(3.45)) print(str[3, 4]) # bytearray函数 print(bytearray("python", encoding="utf-8")) # bytes函数 print(bytes("python", encoding="utf-8")) # memoryview函数 print(memoryview(bytes(123))) ``` - #### 10.2.3 进制转换 - **bin(x)**:将输入的整数x转变为一个前缀为"0b"的二进制字符串。 - **oct(x)**:将输入的整数x转变为一个前缀为"0o"的八进制字符串。 - **hex(x)**:将输入的整数x转变为一个前缀为"0x"的十六进制字符串。 - **ord(x)**:对于输入的单个Unicode字符,返回它对应的Unicode码整数。 - **chr(x)**:chr函数是ord函数的逆函数,其作用是对于输入的整数值x,返回其对应的单个Unicode字符。 ```python # bin 函数 print(bin(3)) # oct 函数 print(oct(3)) # hex 函数 print(hex(3)) # ord 函数 print(ord('c')) # chr 函数 print(chr(99)) ``` - #### 10.2.4 数值操作 - **list(x)**:list函数将传入的参数改变为新的列表并进行返回,除此之外,list本身也是一个可变对象。 - **dict(x)**:dict函数将传入的参数值x改变成新的字典对象并进行返回,字典对象为不可变类型。 - **set(x)**:set函数用来将输入的参数x,改变为新的集合对象,并进行返回,set对象为可变对象,同时它内部的元素都是不可重复的。 - **frozenset(x)**:从名字上可以看出,frozenset函数同样可以完成set函数的功能,但是frozenset对象属于不可变对象。因此无法向frozenset对象中插入数值。 ```python # list 函数 print(list("1234")) print(list()) # dict 函数 print(dict(a=2, b=4)) print(dict()) # set 函数 print(set()) set1 = set([1, 2, 3, 4, 1, 2, 3, 4]) print(set1) set1.add(5) print(set1) # frozenset 函数 forzenset1 = frozenset([1, 2, 3, 4, 1, 2, 3, 41]) print(frozenset1) ``` - **tuple(x)**:tuple函数将传入的参数值x改变成新的元组对象并进行返回,元组对象为不可变类型。 - **enumerate(x)**:enumerate函数返回的是一个枚举对象,输入的参数x是一个可迭代对象。返回的枚举对象通过\_\_next\_\_()方法来返回一个元组,包含了计数值和通过迭代获取得到的x中的数值。 - **range(x)**:range函数通过输入值x生成不可变的数字序列,通常用于在for循环中循环指定的次数。 - **iter(x)**:iter函数根据输入参数x生成一个可迭代对象,并返回该可迭代对象。 ```python # tuple 函数 print(tuple([1, 2, 3, 4])) print(tuple()) # enumerate 函数 for index, value in envmerate("abed"): print(index, ":", value) # range 函数 print(range(10)) print(range(0, 10, 2)) # iter 函数 iter1 = iter([1, 2, 4, 5]) for i in range(3): print(next(iter1)) ``` - **slice(x)**:slice函数主要用作灵活的构建切片,其返回的也是一个slice对象。 - **object()**:在Python中,object类是所有类的基类,object函数不接受任何参数,返回的是一个没有任何特征的对象。 - **super()**:super函数常用在Python类对象,子类对于父类的继承中,子类用来引用父类中的对象和方法,而不需要显式的指明父类的名称。 ```python # slice 函数 print(slice(5)) print(slice(0, 5, 2)) # object 函数 print(object()) # super 函数 class A: def __init__(self): self.fathername = "A" class B(A): def __init__(self): super().__init__() self.sonname = "B" print(B().fathername) print(B().sonname) ``` - #### 10.2.5 排序操作 - **sorted(x, key=None, reverse=False)**:对可迭代对象x进行排序,并返回一个排序后的新的对象,key参数可以规定按照何种方式进行比较,而reverse为True时,表示按照递减的方式进行排序 - **reversed(seq )**:对于输入的序列seq进行反转,生成新的可迭代对象并返回。 ```python # sorted 函数 print(sorted([1, 3, 6, 4, 7, 2])) print(sorted([1, 3, 6, 4, 7, 2]), reverse=True) print(sorted({"a":3, "b":6, "c":11}.itens(), key=lambda x: x[1])) # revered 函数 print(list(reversed([1, 2, 3, 4, 5, 6]))) print(list(reversed("abcd"))) ``` - #### 10.2.6. 序列操作 - **all(x)**:针对于可迭代对象x中的每一个元素,判断是否都为真,如果有一个元素为False(0),则返回False。 - **any(x)**:与all函数相同,any函数对于输入的可迭代对象x,判断x中每一个元素是否为True,只要有一个元素为True,则返回True。 - **map(func, iter)**:map函数返回的是一个迭代器,在该迭代器中,func函数将应用于 可迭代对象iter中的每一个元素。 - **filter(func, iter)**:通过func函数来过滤可迭代对象iter中的元素值,并返回由过滤元素所构成新的迭代器。 - **next(iter)**:next函数返回可迭代对象中的下一个元素值。 ```python # all 函数 print(all([i > 2 for i in [1, 2, 3, 4, 5]])) # any 函数 print(any([i > 2 for i in [1, 2, 3, 4, 5]])) # map 函数 def func(x): return x > 3 print(map(func, [1, 2, 3, 4, 5])) for i in map(func, [1, 2, 3, 4, 5]): print(i, end=' )t') # filter 函数 print(filter(func, [1, 2, 3, 4, 5])) for i in filter(func, [1, 2, 3, 4, 5]): print(i, end=' It') # next 函数 iterl = iter([1, 2, 3]) for i in range(3): print(next(iterl), end=' It') ``` - **zip(\*iter)**:根据多个不同的迭代器,进行对应位置元素的聚合,并返回一个新的迭代器。 ```python # zip 函数 for a, b in zip([1, 2, 3, 4, 5], "abcde"): print(a, b) ``` - **reduce(func,sequence\[,initial\])**:将双参数的函数func以迭代的方式从左到右依次应用至序列seq中每个元素,最终返回单个值作为结果。在Python2.x中是内置函数,Python3.x中需要从functools中导入reduce函数再使用。 ```python import functools def add(x, y): # 两数相加 return x + y sum1 = functools.reduce(add, [1, 2, 3, 4, 5]) # 计算列表和:1+2+3+4+5 sum2 = functools.reduce(lambda x, y: x + y, [1, 2, 3, 4, 5]) # 使用lambda函数计算列表和 print(sum1) print(sum2) ``` - #### 10.2.7 对象元素操作 - **help(object)**:通过help函数可以帮助用户来查询不同对象的信息,包括内置方法、属性等信息。 - **id(object)**:返回object对象的标识值,这个标识值是一个整数,且在对象的生命周期中保持唯一。 ```python help 函数 help(int) ``` ```python # id 函数 num = 10 print(id(num)) ``` - **hash(object)**:如果object对象有对应的哈希值则返回对应的哈希值。 - **type(object)**:type函数用来返回object对象的所属类型。 - **dir(object)**:如果没有实参object,则dir函数返回的是当前本地作用域中的名称列表。如果有实参object,函数会尝试返回该对象的有效属性列表。 - **len(object)**:返回object对象的长度或者是所包含的元素个数。 ```python # hash 函数 print(hash("python")) # type 函数 str1 = "python" list1 = [1, 2] print(type(str1)) print(type(list1)) # dir 函数 list2 = [1, 2, 3, 4] str2 = "ererdfff" print(len(list2)) print(len(str2)) ``` - **repr(object)**:repr函数返回包含一个对象的可打印表示形式的字符串。 - **ascii(object)**:ascii函数与repr的功能相似,ascii函数返回包含一个对象的可打印表示形式的字符串,,但是与repr函数不同的是,ascii()比repr()多一个对于非ASCII编码的字符的转义处理。 - **format(value, format_spec)**:format函数将value转换为由format_spec参数控制的"格式化"表示形式,多用在字符串的格式化处理中。 - **vars(object)**:函数返回模块、类、实例等具有_dict\_\_属性的对象的_dict\_\_属性。 ```python # repr 函数 print(repr([1, 2, 3, 4])) print(repr("python")) # ascii 函数 print(ascii([1, 2, 3, 4])) print(ascii("python")) print("python ()".format(123)) # 按照八进制输出123 print(format(123, 'o')) # 按照十六进制输出123 print(format(123, 'x')) # vars 函数 class A: def _init_(self): self.name = "python" self.age = 10 print(vars(A())) ``` - #### 10.2.8 属性操作 - **isinstance(object, classinfo)**:函数用来判断object对象是否属于classinfo的类型,如果是则返回True,否则返回False。 - **issubclass(class, classinfo)**:如果class是classinfo类的子类,则函数返回True,否则返回False。 ```python # isinstance 函数 print(isinstance("python", str)) print(isinstance("python", int)) # issubclassa 函数 class A: def init_(self): pass class B(A): def _init(self): pass print(issubclass(B, A)) print(issubclass(int, object)) ``` - **hasattr(object, name)**:如果name字符串是object对象的属性之一的名称,则返回True,否则返回False。 - **getattr(object, name)**:返回对象命名属性的值。name必须是字符串。如果字符串name是object对象的属性之一,则返回该属性的值。 - **setattr(object, name, value)**:字符串name是指对于object对象的一个已经存在的属性或者新增属性。只要object对象允许setattr操作,函数会将值value赋给该属性。 - **delattr(object, name)**:字符串name必须是object对象的某个属性的名字。如果object对象允许删除属性,则delattr函数将删除指定的name属性。 - **\_\_import(name)\_\_**:通过动态的方式来导入模块。 - **callable(object)**:如果对象 object 是可调用的就返回True,否则返回False。 ```python # hasattr, getattr, setattr, delattr 函数 class A: def __init__(self): self.name = "python" self.age = 10 self.sex = "male" myclass = A() print(hasattr(myclass, "name")) print(getattr(myclass, "age")) setarrt(myclass, "num", 12345) print(vars(myclass)) delattr(myclass, "name") print(vars(myclass)) # __impot__ 函数 np = __import__("numpy") print(np._version) # callable 函数 print(callable(A)) ``` - #### 10.2.9 变量操作 - **globals()**:返回作用域内的全局变量和其数值所构成的字典。 - **locals()**:与globals函数对应的,locals函数返回的是当前作用域下局部变量和其数值所构成的字典。 ```python # globals 函数 print(globals()) ``` ```python # celocals 函数 def fune(): local_varl = 123 ocal_var2 = "python" print(locals()) fune() ``` - #### 10.2.10 人机交互操作 - **print(\*objects, end='\n', file=sys.stdout)**:将objects的内容打印到file指定的文本流当中,末尾以end作为结束。 - **input()**:用来读取用户的输入值。 - **open(file, mode='r')**:打开file并返回对应的file object对象,mode对应的是向file文件进行读或者是写等操作。如果该文件不能被打开,那么程序会引发OSError报错。 ```python # print 函数 print("python") print(124) #input 函数 input("请输入数值:") # open 函数 with open("a.txt", 'w') as fw: fw.write("python") fw.write("in") with open("a.txt", 'r') as fr: print(fr.readlines()) ``` - #### 10.2.11 编译操作 - **compile(source,, mode)**:函数将source编译成代码,然后被exec函数或者是eval函数执行,其中mode参数表示的是编译代码所需要使用的模式。 - **exec(object)**:exec函数支持动态的来执行Python代码,其中object必须是字符串或者是代码对象。如果是字符串,则字符串会被解析成Python语句来执行,如果是目标代码的话,则直接执行。 - **eval(expression)**:eval函数会将字符串expression当成有效的表达式来求值并返回计算结果。eval函数只能单个运算表达式,而不能是复杂的代码逻辑或者是赋值运算。 ```python # complie, exec 函数 str_code = "print ([i**2 for i in range (5) ])" compilel = compile(str_code, '', mode="exec") exec(compilel) # eval 函数 print(eval("12*34+4")) print(eval("float (200) ")) ``` - #### 10.2.12 装饰器函数 - **classmethod()**:classmethod的作用是将一个方法封装成类方法,可以在不创建类对象的前提下调用该装饰器修似的方法。 - **staticmethod()**:staticmethod方法是将类中的方法转换为静态的方法,静态方法不会接受隐式的参数,同样也可以在不创建类对象的前提下调用静态方法。 - **property()**:作为装饰器,property可以将类方法转换为类属性来使用。 ```python class MyClass(object): district = "BeiJing" def __init__(self, firstname="Joe", lastname="Harris"): self.firstname = firstname self.lastname = lastname self.age = 20 # property, classmethod, staticmethod 函数 @property def fullName(self): print("ful1Name: (). 1)").format(self.firstname, self.lastname) @classnethod def showDistrict(cls): print("I an in ".format(cls.district())) @staticmethod def showStaticmethod(): print("this is showStaticmethod") MyClass("hah", "lala").fullName MyClass.showDistrict() MyClass.showStaticmethod() ``` ## 11. Python多线程 ### 11.1 进程和线程 进程就是程序执行的载体,我们打开的每个软件、游戏,执行的每一个Python脚本都是启动一个进程。 线程是进程中执行运算的最小单位,是进程中的一个实体,是被系统独立调度和分派的基本单位。例如车间的生产是一个进程,那每个流水线就是它的一个线程。 线程自己不拥有系统资源,只拥有一点在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所拥有的全部资源。一个线程可以创建和撤消另一个线程,同一进程中的多个线程之间可以并发执行。 进程提供线程执行程序的前置要求,线程在重组的资源配备下,去执行程序。Python3线程中常用的两个模块是"\_thread"和"threading"(推荐使用)。 thread模块已被废弃。用户可以使用threading模块代替。所以,在Python3中不能再使用"thread"模块。为了兼容性,Python3将thread重命名为"\_thread"。 ### 11.2 线程对象Thread ```python class threading.Thread(grounp=None, target=None, name=None, args={}, kwargs={}) ``` - **group**:应该为None,为了日后扩展ThreadGroup类实现而保留。 - **target**:是用于run()方法调用的可调用对象,默认是None,表示不需要调用任何方法。 - **name**:线程名称,默认情况下,由"Thread-N"格式构成一个唯一的名称,其中N是小的十进制数。 - **args**:用于调用目标函数的参数元组,默认是()。 - **kwargs**:用于调用目标函数的关键字参数字典,默认是{}。 ### 11.3 Thread类的方法
方法名说明用法
start启动线程
它在一个线程里最多只能被调用一次。它安排对象的run()方法在一个独立的控制进程中调用
start()
run线程活动run()
join阻塞知道线程执行结束
这会阻塞调用这个方法的线程,知道被调用join()的线程终结
不管是正常终结还是抛出未处理异常,或者知道发生超时,超时选项是可选的。
一定要在join()后调用is_alive()才能判断是否发生超时,如果线程仍然存活,则join()超时。
一个线程可以被join()很多次
join(timeout=None)
getName获取线程的名字getName()
setName设置线程的名字setName(name)
is_alive判读线程是否存活is_alive()
setDaemon守护线程setDaemon(True)
### 11.4 创建Thread对象 - #### 11.4.1 直接创建Thread 将一个函数对象从类的构造器传递进去,这个对象就是回调函数,用来处理任务。 ```python from threading impport Thread def task(): print('i am sub_thread') if __name__=='__main__': t = Thread(target=task) t.start() print('i an main-thread') ``` - #### 11.4.2 继承Thread类 编写一个自定义类继承Thread,然后重写run()方法,在run()方法中编写任务处理代码,然后创建这个Thread的子类。 ```python from threading impport Thread def task(): print('i am sub_thread') class MyThread(Thread): def run(self): task() if __name__=='__main__': t = MyThread() t.start() print('i an main-thread') ``` ### 11.5 多线程 多线程类似于车间生产时,有多条流水线在运作,可以提高生产的效率。创建Thread对象,然后让它们运行,每个Thread对象代表一个线程,在每个线程中我们可以让程序处理不同的任务,这就是多线程编程。 这里创建了7个线程执行任务,同时调用join方法等待线程执行结束,比单一主线程执行更加快速。 ```python import threading def func(n): while n > 0: print("当前线程数:",threading.activeCount()) n -= 1 threads = [] for x in range(5): t = threading.Thread(target=func, args=(2,)) threads.append(t) t.start() for t in threads: t.join() print("主线程:",threading.current_thread().name) ``` ### 11.6 线程同步 如果多个线程共同对某个数据修改,则可能出现不可预料的结果,为了保证数据的正确性,需要对多个线程进行同步。使用Thread对象的Lock和Rlock可以实现简单的线程同步。 - #### 11.6.1 LOCK锁 - **acquire(blocking=True, timeout=-1)**:使线程进入同步阻塞状态,尝试获得锁定。当调用时参数blocking设置为True,阻塞直到锁被释放,然后将锁锁定并返回True。在参数blocking被设置为False,将不会发生阻塞。 - **release()**:释放锁。使用前线程必须已获得锁定,否则将抛出异常。 release()只在锁定状态下调用,它将状态改为非锁定并立即返回。如果尝试释放一个非锁定的锁,则会引发RuntimeError异常。对于Lock对象而言,如果一个线程连续两次release,会使得线程死锁。所以Lock不常用,一般采用Rlock进行线程锁的设定。 ```python import threading def job1(): global A, lock lock.acquire() for i in range(10): A += 1 print('job1', A) lock.release() def job2(): global A, lock lock.acquire() for i in range(10): A += 10 print('job2', A) lock.release() if __name__ == '__main__': lock = threading.Lock() A = 0 t1 = threading.Thread(target=job1) t2 = threading.Thread(target=job2) t1.start() t2.start() t1.join() t2.join() ``` 执行后,t1先获得锁,执行完成后再释放锁,t2再获得锁,继续执行后再释放锁,这样避免同时处理,导致数据出错。 - #### 11.6.2 RLock锁 - **acquire(blocking=True, timeout=-1)**:可以阻塞或非阻塞地获得锁,当无参数调用时,如果这个线程已经拥有锁,递归级别增加一,并立即返回。否则,如果其他线程拥有该锁,则阻塞至该锁解锁。 一旦锁被解锁(不属于任何线程),则抢夺所有权,设置递归等级为一,并返回。如果多个线程被阻塞,等待锁被解锁,一次只有一个线程能抢到锁的所有权。在这种情况下,没有返回值。 - **release()**:释放锁,自减递归等级。如果减到零,则将锁重置为非锁定状态(不被任何线程拥有),并且,如果其他线程正被阻塞着等待锁被解锁,则仅允许其中一个线程继续。如果自减后,递归等级仍然不是零,则锁保持锁定,仍由调用线程拥有。 ```python import threading lock = threading.RLock() ret = lock.acquire() print(ret) ret = lock.acquire(timeout=3) print(ret) ret = lock.acquire(True) print(ret) ret = lock.acquire(False) print(ret) lock.release() lock.release() lock.release() lock.release() ``` RLock(可重入锁)是一个可以被同一个线程请求多次的同步指令。RLock使用了"拥有的线程"和"递归等级"的概念,处于锁定状态时,RLock被某个线程拥有。拥有RLock的线程可以再次调用acquire(),释放锁时需要调用release()相同次数。 RLock相当于包含一个锁定池和一个初始值为0的计数器,每次成功调用acquire()/release(),计数器将+1/-1,为0时锁处于未锁定状态。 ## 12. Python PiP的使用 ### 12.1 简单介绍 pip是Python包管理工具,该工具提供了对Python包的查找、下载、安装和卸载的功能,现在大家用到的所有包不是自带的就是通过pip安装的。Python 2.7.9+或Python 3.4以上版本都自带pip工具。 ### 12.2 下载安装 打开命令行终端,输入"**pip**",如果出现下图的信息则说明已经安装了pip。 如果你还未安装,则可以在命令行终端输入指令"**sudo apt install python3-pip**"安装。指令执行后会需要输入设置的权限密码,然后选择"**y**"继续安装。 ### 12.3 常用指令 (1) install:安装指令包,格式为"**pip3 install \**",packagename为实际要操作的包名。 ```bash pip3 install numpy ``` (2) uninstall:卸载指定包,格式为"**pip3 uninstall \**"。 ```bash pip3 uninstall numpy ``` (3) list:列出已安装的包名,格式为"**pip3 list**"。 ```bash pip3 list ``` (4) show:查看已安装包的信息,格式为"**pip3 show \**"。 ```bash pip3 show numpy ``` ## 13. Python Numpy基础操作 ### 13.1 简单介绍 NumPy(Numerical Python) 是Python语言的一个扩展程序库,支持大量的维度数组与矩阵运算,此外也针对数组运算提供大量的数学函数库。 (1) 在某些方面,Numpy数组与Python内置的list列表类型非常相似,是Python数据科学的核心工具。 (2) numpy一维数组可以理解为向量,二维数组即是数据框(更准确来说,对应R里的matrix矩阵)....。 (3) numpy数组与python里的list列表最大的不同是前者需包含同一种数据类型才行,后者则没有此限制。 ### 13.2 Numpy的导入 Numpy是一个第三方库,需要先安装,打开命令行终端输入指令安装"**pip3 install numpy**"。 ```bash pip3 install numpy ``` 然后我们需要在python中导入,直接用"**import numpy**"就可以导入。我们可以使用"**import numpy as np**"取"**np**"作为别名。 ### 13.3 创建数组 (1) np.array():直接创建。 ### 13.4 固定取值 - **np.zeros(n, dtype=int)**:创建长度为n,值全为0的整型的一维数组。 - **np.ones((a,b), dtype=float)**:创建a行b列,值全为1的浮点型的二维数组。 - **np.full((a,b),x, dtype=int/float)**:创建a行b列,值全为x的二维数组。 ```python np.full((3, 3), 1.11) # array([1.11, 1.11, 1.11], # [1.11, 1.11, 1.11], # [1.11, 1.11, 1.11]) ``` ### 13.5 规律分布 - **np.arange()**:等差数列。 - **np.random.randint()**:随机整数。 - **np.random.random(10)**:长度为10,符合0~1均匀分布的一维数组。 - **np.random.normal(0, 1, c(2,3))**:两行三列的,符合均值为0,标准差为1正态分布的二维数组。 ### 13.6 数值取子集 - #### 13.6.1 索引从0开始 (1) 类似python的list取子集方式,numpy数组的索引也是从0开始。 (2) 负数的索引可以理解为倒数第n个值。 - #### 13.6.2 取单个值的子集 直接用元素下标查看。 - #### 13.6.3 切片取子集 (1) 对于长度为10的一维数组x1,x1\[0:5\]表示索引0到索引4的子集(不包括索引5),默认步长为1。 (2) \[a:b\:c\]中,a为0时,可省略;a,b均省略时,则表示全集。 (3) 步长为负数时,表示逆序取子集。 - #### 13.6.4 列表多个索引值取子集 按索引值依次取出。 - #### 13.6.5 逻辑布尔值取子集 - #### 13.6.6 创建不相关联的子集副本 copy()方法可创建不相关联的子集副本。 ### 13.6.7 数组维度变换 (1) 矩阵转置T()方法:行列转换。 (2) 维度转换reshaple()方法:按照希望的可执行的维度结果转换。 ### 13.7 数组的合并与拆分 - #### 13.7.1 数组合并 (1) concatenate():可连接两个一维数组,或者按行/列合并两个二维数组。 (2) vstack():纵向合并两个数组,只要这两个数组的列数相同。 (3) hstack():横向合并两个数组,只要这两个数组的行数相同。 - #### 13.7.2 数组拆分 (1) split():拆分一维数组,参数的索引值指定分裂点的位置,当函数结果返回多个对象时,在等号前就要设置相应个数的对象名 (2) vsplit():横向拆分一个二维数组(上下),同理hsplit(),纵向拆分一个二维数组数组拆分(左右)。