当前位置:   article > 正文

Python基本语法

python基本语法

1 基础语法

1.1 字面量

含义:在代码中,被写下来的的固定的值,称之为字面量

1.1.1 常用的值类型

1.1.2 如何在代码中表达:

1.2 注释

注释:在程序代码中对程序代码进行解释说明的文字。

作用:注释不是程序,不能被执行,只是对程序代码进行解释说明,让别人可以看懂程序代码的作用,能够大大增强程序的可读性。

1.2.1 单行注释

以 #开头,#右边 的所有文字当作说明,而不是真正要执行的程序,起辅助说明作用

1.2.2 多行注释

以一对三个双引号引起来 (“”“注释内容”“”)来解释说明一段代码的作用使用方法

1.3 变量

变量:在程序运行时,能储存计算结果或能表示值的抽象概念。

特征:变量存储的数据,是可以发生改变的。(为了重复使用)

1.4 数据类型

通过type()语句来得到数据的类型:

type(被查看类型的数据)
  • 1
  1. 在print语句中,直接输出类型信息
  2. 用变量存储type()的结果(返回值)
  3. 通过type(变量)可以输出类型,查看的是:变量存储的数据的类型。因为变量无类型,但是它存储的数据有

1.5 类型转换

如:

  1. 从文件中读取的数字,默认是字符串,我们需要转换成数字类型
  2. 后续学习的input()语句,默认结果是字符串,若需要数字也需要转换
  3. 将数字转换成字符串用以写出到外部系统

  1. 任何类型,都可以通过str(),转换成字符串
  2. 字符串内必须真的是数字,才可以将字符串转换为数字
  3. 浮点数转整数会丢失精度,也就是小数部分

1.6 标识符

标识符:是用户在编程的时候所使用的一系列名字,用于给变量、类、方法等命名。

规则内容限定 / 大小写敏感 / 不可使用关键字

命名中只允许出现英文 / 中文 / 数字 / 下划线这四类元素,其余任何内容都不被允许。

规范见名知意 / 下划线命名法 / 英文字母全小写

1.7 运算符

1.7.1 算术运算符

1.7.2 赋值运算符

1.7.3 复合赋值运算符

1.8 字符串扩展

1.8.1 字符串的三种定义方式
  1. 双引号定义法:“字符串”
  2. 单引号定义法:‘字符串’
  3. 三引号定义法:“”“字符串”“”
    1. 从三个引号开始,到下一个三个引号结束的范围内,均是字符串
    2. 三引号定义法,和多行注释的写法一样,同样支持换行操作。使用变量接收它,它就是字符串;不使用变量接收它,就可以作为多行注释使用。

如果定义的字符串本身包含单引号/双引号:

  • 单引号定义法,可以内含双引号
  • 双引号定义法,可以内含单引号
  • 可以使用转移字符(\)来将引号解除效用,变成普通字符串
1.8.2 字符串拼接

通过+号完成:

字符串无法和非字符串变量进行拼接,因为类型不一致,无法接上

1.8.3 字符串格式化

通过**%s**,完成字符串和变量的快速拼接

  • % 表示:我要占位
  • s 表示:将变量变成字符串放入占位的地方
  • 多个变量占位,变量要用括号括起来,并按照占位的顺序填入。

python支持的常用数据类型占位

1.8.4 格式化的精度控制

浮点数19.99,变成了19.990000输出 — 需要“数字精度控制”

使用**辅助符号"m.n"**来控制数据的宽度和精度

  • m,控制宽度,要求是数字(很少使用),设置的宽度小于数字自身,不生效
  • .n,控制小数点精度,要求是数字,会进行小数的四舍五入

示例:

  1. %5d:表示将整数的宽度控制在5位,如数字11,被设置为5d,就会变成:[空格][空格][空格]11,用三个空格补足宽度。

  2. %5.2f:表示将宽度控制为5,将小数点精度设置为2

    小数点和小数部分也算入宽度计算。如,对11.345设置了%7.2f 后,结果是:[空格][空格]11.35。2个空格补足宽度,小数部分限制2位精度后,四舍五入为 .35

  3. %.2f:表示不限制宽度,只设置小数点精度为2,如11.345设置%.2f后,结果是11.35

通过**f"内容{变量}"**的格式来快速格式化,不做精度控制,也不理会类型,适用于快速格式化字符串。

1.8.5 对表达式进行格式化

表达式:一个具有明确结果的代码语句,如 1 + 1、type(“字符串”)、3* 5等

在变量定义的时候,如 age = 11 + 11,等号右侧的就是表达式,也就是有具体的结果,将结果赋值给了等号左侧的变量

在无需使用变量进行数据存储的时候,可以直接格式化表达式,简化代码:

  • f"{表达式}"
  • “%s\%d\%f”% (表达式、表达式、表达式)

1.9 数据输入

  1. input()语句的功能是,获取键盘输入的数据
  2. 可以使用:input(提示信息),用以在使用者输入内容之前显示提示信息。
  3. ⭐ 无论键盘输入什么类型的数据,获取到的数据永远都是字符串类型

2 判断语句(if语句)

2.1 布尔类型和比较运算符

布尔类型的字面量:

  • True 表示真(是、肯定)
  • False 表示假 (否、否定)
  1. 定义变量存储布尔类型数据:变量名称 = 布尔类型字面量
  2. 使用比较运算符进行比较运算得到布尔类型的结果

2.2 if语句

2.2.1 if语句的基本格式
  • 判断语句的结果,必须是布尔类型True或False
  • True会执行if内的代码语句,False则不会执行
  1. 归属于if判断的代码语句块,需在前方填充4个空格缩进
  2. Python通过缩进判断代码块的归属关系
  3. else后,不需要判断条件
  4. 和if的代码块一样,else的代码块同样需要4个空格作为缩进
  5. elif 语句可以写多个,空格缩进同样不可省略
2.2.2 判断语句的嵌套

有很多场景,不仅仅是多个并列条件,还会有满足前置条件才会二次判断的多层判断需求。

嵌套的关键点,在于:空格缩进,通过空格缩进来决定语句之间的:层次关系

2.3 循环语句(while语句和for语句)

2.3.1 while循环

2.3.1.1 while循环的基础语法

  1. 只要条件满足,会无限循环执行
  2. while的条件需得到布尔类型,True表示继续循环,False表示结束循环
  3. 需要设置循环终止的条件,如i += 1配合 i < 100,就能确保100次后停止,否则将无限循环
  4. 空格缩进和if判断一样,都需要设置
2.3.1.2 while循环的嵌套应用
  1. 同判断语句的嵌套一样,循环语句的嵌套,要注意空格缩进。
  2. 基于空格缩进来决定层次关系
  3. 注意条件的设置,避免出现无限循环(除非真的需要无限循环)

2.3.2 for循环

2.3.2.1 for循环的基础语法

while循环的循环条件是自定义的,自行控制循环条件;for循环是一种”轮询”机制,从待处理数据集中逐个取出数据赋值给临时变量

  1. 循环内的语句,需要有空格缩进。
  2. 同while循环不同,for循环无法定义循环条件,只能被动取出数据处理。
  3. 只能从被处理的数据集中依次取出内容进行处理,所以理论上讲无法构建无限循环(被处理的数据集不可能无限大)。
2.3.2.2 range语句

range(num):获取一个从0开始,到num结束的数字序列(不含num本身) 如:range(5) — [0, 1, 2, 3, 4]

range(num1,num2):获得一个从num1开始,到num2结束的数字序列(不含num2本身) 如:range(5, 10) — [5, 6, 7, 8, 9]

range(num1, num2, step):获得一个从num1开始,到num2结束的数字序列(不含num2本身)数字之间的步长,以step为准(step默认为1) 如:range(5, 10, 2) — [5, 7, 9]

2.3.2.3 变量作用域

.for循环中的临时变量,其作用域限定为:循环内

  1. 是编程规范的限定,而非强制限定
  2. 不遵守也能正常运行,但是不建议这样做
  3. 如需访问临时变量,可以预先在循环外定义它

2.3.2.4 for循环的嵌套应用

和while循环一样,需要注意缩进,通过缩进确定层次关系

2.4 循环中断(break和continue)

continue关键字

  1. 中断本次循环,直接进入下一次循环;
  2. 可以用于for循环和while循环,效果一致;
  3. 只可以控制它所在的循环临时中断

break关键字

  1. 直接结束所在循环
  2. 可以用于for循环和while循环,效果一致
  3. 只可以控制它所在的循环永久中断

3 函数

3.1 函数的定义

函数:是组织好的,可重复使用的,用来实现特定功能的代码段。

优点:

  1. 提高程序的复用性,减少重复性代码,提高开发效率
  2. 将功能封装在函数内,可供随时随地重复利用
3.1.1 调用

函数名(参数)

  • 参数/返回值如不需要,可以省略
  • 函数必须先定义后使用

3.2 函数的参数

传入参数:在函数进行计算的时候,接受外部(调用时)提供的数据

定义

函数定义中的参数称为形式参数(形参),参数之间使用逗号分割。

函数调用中的参数称为实际参数(实参),按照顺序传入数据,使用逗号分隔。

传入参数的数量是不受限制的,可以不使用参数,也可以仅使用任意N个参数。

3.2.1 位置参数

调用函数时根据函数定义的参数位置来传递参数

传递的参数和定义的参数的顺序及个数必须一致

3.2.2 关键字参数

函数调用时通过**“键=值”**形式传递参数.

作用: 可以让函数更加清晰、容易使用,同时也清除了参数的顺序需求。

⭐ 函数调用时,如果有位置参数,必须在关键字参数的前面,但关键字参数间不存在先后顺序。

3.2.3 缺省参数

缺省参数(默认参数):用于定义函数,为参数提供默认值,调用函数时可不传该默认参数的值

作用:当调用函数时没有传递参数,就会使用默认是用缺省参数对应的值.

⭐ 所有位置参数必须出现在默认参数前,包括函数定义和调用

⭐ 函数调用时,如果为缺省参数传值,则修改默认参数值, 否则使用这个默认值。

3.2.4 不定长参数

不定长参数(可变参数):用于不确定调用的时候会传递多少个参数(不传参也可以)的场景。

3.2.4.1 位置传递

传进的所有参数都会被args变量收集,它会根据传进参数的位置合并为一个元组(tuple)。

3.2.4.2 关键字传递

参数是**“键=值”的形式**的情况下, 所有的“键=值”都会被kwargs接受, 同时会根据“键=值”组成字典。

3.3 函数的返回值

3.3.1 返回值

“返回值”,就是程序中函数完成事情后,最后给调用者的结果

⭐ 函数体在遇到return后就结束了,所以写在return后的代码不会执行

3.3.2 多返回值

按照返回值的顺序,写对应顺序的多个变量接收即可

变量之间用逗号隔开,支持不同类型的数据return

3.3.3 None类型

如果函数没有使用return语句返回数据,函数也有返回值。无返回值的函数,实际上就是返回了:None这个字面量,其类型是:<class ‘NoneType’>

用法:

  1. 用在函数无返回值上
  2. 用在if判断上
    1. 在if判断中,None等同于False
    2. 一般用于在函数中主动返回None,配合if判断做相关处理
  3. 用于声明无内容的变量上
    1. 定义变量,但暂时不需要变量有具体值,可以用None来代替

3.4 函数说明文档

通过多行注释的形式,对函数进行说明解释,其内容应写在函数体之前。

3.5 函数的嵌套调用

嵌套调用:一个函数里面又调用了另外一个函数

函数A中执行到调用函数B的语句,会将函数B全部执行完成后,继续执行函数A的剩余内容

3.6 变量的作用域

作用域:变量的作用范围(变量在哪里可用,在哪里不可用)

3.6.1 局部变量

局部变量:定义在函数体内部的变量,即只在函数体内部生效。

作用:在函数体内部,临时保存数据,即当函数调用完成后,则销毁局部变量。

3.6.2 全局变量

全局变量:在函数体内、外都能生效的变量

3.6.3 global关键字

使用global关键字可以在函数内部声明变量为全局变量

3.7 匿名函数

3.7.1 函数作为参数传递

  • 函数本身是可以作为参数,传入另一个函数中进行使用的。
  • 将函数传入的作用在于:传入计算逻辑,而非传入数据。

3.7.2 lambda匿名函数

  • def关键字,可以定义带有名称的函数
  • lambda关键字,可以定义匿名函数(无名称)

有名称的函数,可以基于名称重复使用;无名称的匿名函数,只可临时使用一次。

lambda 传入参数: 函数体(一行代码)

  • 传入参数表示匿名函数的形式参数,如:x, y 表示接收2个形式参数;
  • 函数体 — 函数的执行逻辑,只能写一行,无法写多行代码。

4 数据容器

数据容器:一种可容纳多份数据的数据类型,容纳的每一份数据称之为1个元素。

每一个元素,可以是任意类型的数据,如字符串、数字、布尔等。

4.1 list(列表)

4.1.1 定义

列表内的每一个数据,称之为元素。

  • 以**[ ]**作为标识
  • 列表内每一个元素之间用**, 逗号**隔开。
  • 各元素可以为不同的数据类型,支持嵌套。

4.1.2 下标索引

列表[下标索引]:用于取出特定位置的元素

对于嵌套列表:

⭐ 下标索引的取值范围,超出范围无法取出元素,并且会报错。

4.1.3 常用操作

列表.index(元素)查找指定元素在列表的下标,如果找不到,报错ValueError。
列表[下标] = 值直接对指定下标(正向、反向下标均可)的值进行:重新赋值(修改)。
列表.insert(下标, 元素)在指定的下标位置,插入指定的元素。
列表.append(元素)将指定元素,追加到列表的尾部。
列表.extend(其它数据容器)将其它数据容器的内容取出,依次追加到列表尾部。
del 列表[下标]删除元素
列表.pop(下标)删除元素
列表.clear()清空列表内容
列表.count(元素)统计某元素在列表内的数量
len(列表)统计列表共有多少元素

4.1.4 遍历

4.1.4.1 while循环

使用列表[下标]的方式取出列表元素

定义一个变量表示下标,从0开始,循环条件为 下标值 < 列表的元素数量

index = 0
while index < len(列表)
	元素 =  列表[index]
	对元素进行处理
	index += 1
  • 1
  • 2
  • 3
  • 4
  • 5
4.1.4.2 for循环
for 临时变量 in 数据容器:
	对临时变量进行处理
  • 1
  • 2
  • 循环控制上:
    • while循环可以自定循环条件,并自行控制
    • for循环不可以自定循环条件,只可以一个个从容器内取出数据
  • 无限循环上:
    • while循环可以通过条件控制做到无限循环
    • for循环理论上不可以,因为被遍历的容器容量不是无限的
  • 使用场景上:
    • while循环适用于任何想要循环的场景
    • for循环适用于遍历数据容器的场景或简单的固定次数循环场景

4.2 tuple(元组)

4.2.1 定义

定义元组使用小括号,且使用逗号隔开各个数据,数据可以是不同的数据类型。

  • 元组只有一个数据时,后面要添加逗号
  • 一旦定义完成,就不可修改。
  • 元组也支持嵌套。
# 定义元组字面量
(元素, 元素, ..., 元素)
# 定义元组变量
变量名称 = (元素, 元素, ..., 元素)
# 定义空元组
变量名称 = () # 方式1
变量名称 = tuple() # 方式2
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

4.2.2 操作

index()查找某个数据,如存在返回对应下标,否则报错
count()统计某个数据在当前元组出现的次数
len(元组)统计元组内的元素个数
  • 不可以修改元组的内容,否则会直接报错
  • 可以修改元组内的list的内容(修改元素、增加、删除、反转等)
  • 不可以替换list为其它list或其它类型

4.3 str(字符串)

字符串:可以存放任意数量的字符。

4.3.1下标索引

  • 从前向后,下标从0开始
  • 从后向前,下标从-1开始

4.3.2 常用操作

字符串 — 无法修改

字符串.index(字符串)查找特定字符串的下标索引值
字符串.replace(字符串1,字符串2)将字符串1全部替换为字符串2,得到了一个新字符串
字符串.split(分隔符字符串)按照指定的分隔符字符串,将字符串划分为多个字符串,并存入列表对象中。
字符串.strip()去前后空格
字符串.strip(字符串)去前后指定字符串(按照单个字符去除
字符串.count(字符串)统计字符串中某字符串的出现次数
len(字符串)统计字符串的长度

4.4 数据容器(序列)的切片

序列:内容连续、有序,可使用下标索引的一类数据容器。(如:列表、元组、新字符串)

4.4.1 切片

序列[起始下标:结束下标:步长]:从序列指定位置开始,依次取出元素,到指定位置结束,得到一个新序列

  1. 起始下标:表示从何处开始,可以留空,留空视作从头开始
  2. 结束下标:(不含)表示何处结束,可以留空,留空视作截取到结尾
  3. 步长:表示依次取元素的间隔
    1. 步长1:一个个取元素
    2. 步长N:每次跳过N-1个元素取
    3. 步长为负:反向取(起始下标和结束下标也要反向标记)
my_str="12345
new_str=my_str[:-1]	#从头(最后)开始,到尾结束,步长-1(倒序)
print(new_str)	#结果:“54321”

my_list = [1, 2, 3, 4, 5]
new_list = my_list[3:1:-1]	#从下标3开始,到下标1(不含)结束,步长-1(倒序)
print(newlist)	#结果:[4,3]

my_tuple = (1,2,3, 4, 5)
new_tuple =my_tuple[:1:-2]	#从头(最后)开始,到下标1(不含)结束,步长-2(倒序)
print(new_tuple)	#结果:(5,3)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

4.5 set(集合)

4.5.1 定义

  • 不支持元素的重复(自带去重功能)、并且内容无序。
  • 集合是无序的,不支持下标索引访问。
# 定义集合字面量
{元素, 元素, ..., 元素}
# 定义集合变量
变量名称 = {元素, 元素, ..., 元素}
# 定义空集合
变量名称 = set()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

4.5.2 操作

集合.add(元素)添加新元素
集合.remove(元素)将指定元素从集合内移除
集合.pop()从集合中随机取出元素
集合.clear()清空集合
集合1.difference(集合2)取出集合1和集合2的差集(1有2无),得到一个新集合。
集合1.difference_update(集合2)集合1内,删除和集合2相同的元素。(集合1被修改)
集合1.union(集合2)将集合1和集合2组合成新集合。
len(集合)统计集合内有多少元素

4.5.3 遍历

只支持for循环遍历;

集合不支持下标索引,因此不支持while循环。

4.6 dict(字典、映射)

4.6.1 定义

字典的定义使用{},存储的元素是一个个键值对;

每一个键值对包含Key和Value(用冒号分隔);

键值对之间使用逗号分隔;

Key和Value可以是任意类型(key不可为字典);— 字典可以嵌套

Key不可重复,重复会对原有数据覆盖。

# 定义字典字面量
{key: value, key: value, ..., key: value}
# 定义字典变量
my_dict = {key: value, key: value, ..., key: value}
# 定义空字典
my_dict = {}	# 空字典定义方式1
my_dict =dict{}	# 空字典定义方式2
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

字典不可以使用下标索引,但可通过key值检索对应value

4.6.2 操作

字典[Key]获取指定Key对应的Value值
字典[Key] =Value添加或更新键值对
字典.pop(Key)取出Key对应的Value并在字典内删除此Key的键值对
字典.clear()清空字典
字典.keys()获取字典的全部Key,可用于for循环遍历字典
len(字典)计算字典内的元素数量

4.7 数据容器的通用操作

列表元组字符串集合字典
元素数量支持多个支持多个支持多个支持多个支持多个
元素类型任意任意仅字符任意Key: Value(Key:除字典外任意类型 Value:任意类型)
下标索引支持支持支持不支持不支持
重复元素支持支持支持不支持不支持
可修改性支持不支持不支持支持支持
数据有序
使用场景可修改、可重复的一批数据不可修改、可重复的一批数据一串字符的记录不可重复的数据不可重复的数据记录场景以Key检索Value的数据记录场景
4.7.1 遍历
  • 5类数据容器都支持for循环遍历
  • 列表、元组、字符串支持while循环,集合、字典不支持(无法下标索引)
功能描述
通用for循环遍历容器(字典是遍历key)
max容器内最大元素
min()容器内最小元素
len()容器元素个数
list()转换为列表
tuple()转换为元组
str()转换为字符串
set()转换为集合
sorted(序列, [reverse=True])排序,reverse=True表示降序,得到一个排好序的列表

4.7.2 字符串比较大小

字符串进行比较 — 基于数字的ASCII码值大小进行比较

按位比较:一位位进行对比,只要有一位大,那么整体就大。

如字符串"abc"和"abd",由于字符b的ACSII码值大于字符d,因此字符串"abd"大。

又如字符串"a"和"ab",第一位相同,字符"b"比较大,因此字符串"ab"大于字符串"a"。

5 文件操作

5.1 文件的编码

文本文件 → 编码技术 → 0/1

可用编码:UTF-8/GBK/Big5/…

5.1 文件的读取

打开文件→读写文件→关闭文件

操作功能
f = open(file, mode, encoding)打开文件获得文件对象
f.read(num)读取指定长度字节, 不指定num读取文件全部
f.readline()读取一行
f.readlines()读取全部行,得到列表
for line in f for linesfor循环文件行,一次循环得到一行数据
f.close()关闭文件对象
with open() as f通过withopen语法打开文件,可以自动关闭
① open()打开函数

open(name, mode, encoding):打开已存在的文件,或创建一个新文件

name:是要打开的目标文件名的字符串(可以包含文件所在的具体路径)。

mode:设置打开文件的模式(访问模式):只读、写入、追加等。

encoding:编码格式(推荐使用UTF-8)

f =open('python.txt', 'r', encoding="UTF-8")
# f是open函数的文件对象
# encoding的顺序不是第三位,所以不能用位置参数,用关键字参数直接指定
  • 1
  • 2
  • 3
'
运行
r以只读方式打开文件。文件的指针将会放在文件的开头。这是默认模式。
w打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,原有内容会被删除;如果该文件不存在,创建新文件。
a打开一个文件用于追加。如果该文件已存在,新的内容将会被写入到已有内容之后;如果该文件不存在,创建新文件进行写入。
② read()方法

文件对象.read(num):num表示要从文件中读取的数据的长度(单位是字节),如果没有传入num,那么就表示读取文件中所有的数据。

③ readlines()方法

文件对象.readlines():可以按照的方式把整个文件中的内容进行一次性读取,并且返回的是一个列表,其中每一行的数据为一个元素。

f = open('python.txt')
content = f.readlines()

# ['hello world\n', 'abcdefg\n', 'aaa\n', 'bbb\n', 'ccc']
print(content)

# 关闭文件
f.close()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
'
运行
④ readline()方法:

文件对象.readline():一次读取一行内容

⑤ for循环读取文件行
for line in open("python.txt", "r"):
    print(line)
# 每一个line临时变量,就记录了文件的一行数据

  • 1
  • 2
  • 3
  • 4
⑥ close() 关闭文件对象
f = open("python.txt", "r")
f.close()
# 最后通过close,关闭文件对象,也就是关闭对文件的占用
# 如果不调用close,同时程序没有停止运行,那么这个文件将一直被Python程序占用。

  • 1
  • 2
  • 3
  • 4
  • 5
⑦ with open
with open("python.txt", "r") as f:
    f.readlines()

# 通过在with open的语句块中对文件进行操作
# 可以在操作完成后自动关闭close文件,避免遗忘掉close方法
  • 1
  • 2
  • 3
  • 4
  • 5
'
运行

5.3 文件的写入

# 1. 打开文件
f = open('python.txt', 'w')
# 2.文件写入
f.write('hello world')
# 3. 内容刷新
f.flush()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
'
运行
  1. 直接调用write,内容并未真正写入文件,而是会积攒在程序的内存中,称之为缓冲区;
  2. 当调用flush的时候,内容会真正写入文件;
  3. 这样做是避免频繁的操作硬盘,导致效率下降(攒一堆,一次性写磁盘)。

5.4 文件的追加

# 1. 打开文件,通过a模式打开即可
f = open('python.txt', 'a')
# 2.文件写入
f.write('hello world')
# 3. 内容刷新
f.flush()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
'
运行

可以使用”\n”来写出换行符

6 异常、模块与包

6.1 异常

异常(bug):软件出现错误

6.1.1 捕获方法

如果遇到bug:

① 整个程序因为一个BUG停止运行;

② 对BUG进行提醒, 整个程序继续运行。

捕获异常:提前假设某处会出现异常,做好提前准备,当真的出现异常的时候,可以有后续手段。

6.1.1.1 捕获常规异常
try:
	可能要发生异常的语句
except[异常 as 别名:]
	出现异常的准备手段
[else:]
	未出现异常时应做的事情
[finally:]
	不管出不出现异常都会做的事情
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

如果尝试执行的代码的异常类型和要捕获的异常类型不一致,则无法捕获异常。

一般try下方只放一行尝试执行的代码。

try:
    print(name)
except NameError as e:
    print('变量名未定义错误')
  • 1
  • 2
  • 3
  • 4
'
运行
# 捕获所有异常
try:
    print(name)
except Exception as e:
    print(e)
  • 1
  • 2
  • 3
  • 4
  • 5
'
运行
# 捕获异常并输出描述信息
try:
    print(num)
except (NameError, ZeroDivisionError) as e:
    print(e)
  • 1
  • 2
  • 3
  • 4
  • 5
'
运行
try:
    f = open('test.txt', 'r')
except Exception as e:
    f = open('test.txt', 'w')
else:
    print('没有异常时执行的代码')
finally:
    f.close()    # 无论是否异常都执行的代码 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
'
运行

6.1.2 异常的传递

异常具有传递性。

当所有函数都没有捕获异常的时候, 程序就会报错。

6.2 Python模块

6.2.1 模块的导入

[from 模块名] import [ 模块 || 变量 | 函数 | * ] [as 别名]
  • 1
① import 模块名

调用:模块名.功能名()

② from 模块名 import 类、变量、方法等

调用:功能名()

③ from 模块名 import *

调用:功能名()

④ import 模块名 as 别名
⑤ from 模块名 import 功能名 as 别名

⭐ 当导入多个模块,且模块内有同名功能时,调用到的是后面导入的模块的功能。

6.2.2自定义模块

6.2.2.1 __all__

如果一个模块文件中有__all__变量,当使用from xxx import *导入时,只能导入这个列表中的元素。

在这里插入图片描述

6.3 Python包

6.3.1 Python包

从物理上看,包就是一个文件夹,包含**__init__.py** 文件和多个模块文件。

从逻辑上看,包的本质依然是模块

在这里插入图片描述

6.3.2 导入包

方式一:

import包名.模块名

包名.模块名.目标

方式二:必须在__init__.py文件中添加__all__ = [],控制允许导入的模块列表。

from包名 import *

模块名.目标

请添加图片描述

6.3.3 安装第三方包

pip install -i https://pypi.tuna.tsinghua.edu.cn/simple 包名称

7 面向对象

7.1 成员方法

7.1.1 类的定义和使用
class 类名称:
    成员变量
    
    def 成员方法(self, 参数列表):
        成员方法体
        
# 创建类对象
对象 = 类名称()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

class — 关键字

类的属性 — 即定义在类中的变量(成员变量)

类的行为 — 即定义在类中的函数(成员方法)

7.1.2 成员方法的定义语法

self关键字是成员方法定义的时候,必须填写的,用来表示类对象自身。

在方法(类函数)内部,想要访问类的成员变量,必须使用self。

在调用时传参时可以忽略self关键字。

7.2 构造方法(__init__()方法)

  1. 在创建类对象(构造类)的时候,会自动执行。
  2. 在创建类对象(构造类)的时候,将传入参数自动传递给__init__方法使用。
  3. 在构造方法内定义成员变量,需要使用self关键字。
class student:
	name = None
	ag = None
	tel = None
	def __init__(self, name, age, tel):
		self.name = name
		self.age = age
		self.tel = tel
		print("student类创建了一个对象")
stu = Student("alice"31"18500006666")
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

7.3 其它内置方法

方法功能
__init __构造方法,可用于创建类对象的时候设置初始化行为
__str__用于实现类对象转字符串的行为
__It __用于2个类对象进行小于或大于比较
__le __用于2个类对象进行小于等于或大于等于比较
__eq __用于2个类对象进行相等比较
7.3.1 __str__ 字符串方法

当类对象需要被转换为字符串之时,会输出内存地址。

可以通过__str__方法,控制类转换为字符串的行为。

class student:
	def _init__(self, name, age):
		self.name = name
		self.age = age
student = Student("alice"11)
print(student)	# 结果:<__main__.Studentobjectat0x000002200CFD7040>
print(str(student))	# 结果:<__main__.StudentobjectatOx000002200CFD7040>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
class student:
	def _init__(self, name, age):
		self.name = name
		self.age = age
	def _str_(self):
		return f"student类对象,name={self.name},age={self.age}"
student = Student("alice"11)
print(student)	# 结果:Student类对象,name=alice,age=11
print(str(student))	# 结果:Student类对象,name=alice,age=11
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
7.3.2 __lt__ 小于符号比较方法

直接对2个对象进行比较是不可以的,但是在类中实现__lt__方法,即可同时完成:小于符号 大于符号 2种比较

方法名:__lt__

返回值:True 或 False

传入参数:other,另一个类对象

内容:自行定义

class student:
	def _init__(self, name, age):
		self.name = name
		self.age = age
	def _lt_(self, other):
		return self.age < other.age
stu1 = Student("alice"11)
stu2 = Student("bob"13)
print(stu1 < stu2)	# 结果:True
print(stu1 > stu2)	# 结果:Falue
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
7.3.3 __le__ 小于等于比较符号方法

可用于<=、>=两种比较运算符

方法名:__le__

传入参数:other,另一个类对象

返回值:True 或 False

内容:自行定义

class student:
	def _init__(self, name, age):
		self.name = name
		self.age = age
	def _le__(self, other):
		return self.age <= other.age
stu1 = Student("alice"11)
stu2 = Student("bob"13)
print(stu1 <= stu2)	 # 结果:True
print(stu1 >= stu2)	 # 结果:Falue
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
7.3.4 __eq__ 比较运算符实现方法

不实现__eq__方法,对象之间可以比较,但是比较内存地址,也即是:不同对象==比较一定是False结果。

实现了__eq__方法,就可以按照自己的想法来决定2个对象是否相等了。

方法名:__eq__

传入参数:other,另一个类对象

返回值:True 或 False

内容:自行定义

class student:
	def __init__(self, name, age):
		self.name= name
		self.age = age
	def _eq__(self, other):
		return self.age == other.age
stu1 = Student("alice"11)
stu2 = Student("bob"11)
print(stu1 == stu2)		# 结果:True
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

7.4 封装

7.4.1 私有成员

既然现实事物有不公开的属性和行为,作为现实事物在程序中映射的类也应该支持。

类中提供了私有成员的形式(私有成员变量/私有成员方法)来支持。

定义:

私有成员变量:变量名以__开头(2个下划线)

私有成员方法:方法名以__开头(2个下划线)

class Phone:
	IMEI = None					# 序列号
	producer = None				# 厂商
	__current_voltage = None	# 当前电压,私有成员变量
	def call_by_5g(self):
		print("5g通话已开启"def __keep_single_core(self):	# 私有成员方法
		print("让CPU以单核模式运行以节省电量")
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

私有方法无法直接被类对象使用(不对外开放),但可以被其他成员使用;私有变量无法赋值,也无法获取值。

7.5 继承

7.5.1 继承的基础语法

单继承:将从父类那里继承(复制)来成员变量和成员方法(不含私有)

class 类名(父类名):
    类内容体

  • 1
  • 2
  • 3

多继承:一个类可以继承多个父类

class 类名(父类1, 父类2, ..., 父类N):
    类内容体
  • 1
  • 2

多个父类中,如果有同名的成员,那么默认以继承顺序(从左到右)为优先级。

即:先继承的保留,后继承的被覆盖

7.5.2 复写和使用父类成员

复写:在子类中重新定义同名的属性或方法即可。

class Phone:
	IMEI = None#序列号
	producer = "ITCAsT"#厂商
	def call_by_5g(self):
		print("父类的5g通话")
class MyPhone(Phone) :
	proucer = "ITHEIMA"#复写父类属性
	def call_by_5g(self):#复写父类方法
		print"子类的5g通话"
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

一旦复写父类成员,那么类对象调用成员的时候,就会调用复写后的新成员;

如果需要使用被复写的父类的成员,需要特殊的调用方式:

方式1:调用父类成员

使用成员变量:父类名.成员变量

使用成员方法:父类名.成员方法(self)

方式2:使用super()调用父类成员

使用成员变量:super().成员变量

使用成员方法:super().成员方法()

在这里插入图片描述

7.6 类型注解

类型注解:在代码中涉及数据交互的地方,提供数据类型的注解(显式的说明)。

主要功能:

  1. 帮助第三方IDE工具(如PyCharm)对代码进行类型推断,协助做代码提示
  2. 帮助开发者自身对变量进行类型注释
7.6.1 变量的类型注解

变量: 类型 或在注释中进行:# type: 类型

元组类型设置类型详细注解,需要将每一个元素都标记出来

字典类型设置类型详细注解,需要2个类型,第一个是key,第二个是value。

一般无法直接看出变量类型时,会添加变量的类型注解。

类型注解仅仅是提示性的,不是决定性的。

7.6.2 函数(方法)形参列表和返回值的类型注解

def 函数方法名(形参名: 类型, 形参名: 类型, ...) -> 返回值类型 :

7.6.3 Union类型

Union联合类型注解,在变量注解、函数(方法)形参和返回值注解中,均可使用。

my_list: list[union(int, str)] = [1, 2, 'itcast', "itheima"]
my_dict: dict[str, Union[str, int]] = {"name""alice", "age"31}

def func(data: Union[int, str]) -> Union[int, str]:
	pass
  • 1
  • 2
  • 3
  • 4
  • 5

7.7 多态

多态:多种状态,即完成某个行为时,使用不同的对象会得到不同的状态。

在这里插入图片描述

class Animal:
	def speak(self):
		pass
class Dog(Animal):
	def speak(self):
		print("汪汪汪")
class Cat(Animal):
	def speak(self):
		print("喵喵喵")
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
'
运行

多态常作用在继承关系上,如:函数(方法)形参声明接收父类对象,实际传入父类的子类对象进行工作。

父类用来确定有哪些方法,具体的方法实现由子类自行决定。 — 抽象类

抽象类:含有抽象方法的类称之为抽象类

抽象方法:方法体是空实现的(pass)称之为抽象方法

8 Python高阶技巧

8.1 闭包

在函数嵌套的前提下,内部函数使用了外部函数的变量,并且外部函数返回了内部函数,把这个使用外部函数变量的内部函数称为闭包。
在这里插入图片描述

左图中,通过全局变量记录余额,有被修改的风险。

def outer(num1)# 外部函数
    def inner(num2):    # 内部函数
        nonlocal num1
        num1 += num2
        print(num1)
    return inner        # 返回内部函数

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

使用nonlocal关键字修饰外部函数的变量才可在内部函数中修改它

  1. 优点:
    1. 无需定义全局变量即可实现通过函数,持续的访问、修改某个值
    2. 闭包使用的变量的所用于在函数内,难以被错误的调用修改
  2. 缺点:
    1. 由于内部函数持续引用外部函数的值,所以会导致这一部分内存空间不被释放,一直占用内存

8.2 装饰器

装饰器其实也是一种闭包, 其功能就是在不破坏目标函数原有的代码和功能的前提下,为目标函数增加新功能。

8.2.1 一般写法(闭包写法)
def outer(func):
	def inner():
		print("我要睡觉了")
		func ()
		print("我起床了")
	return inner

def sleep():
	import random
	import time
	print("睡眠中...")
	time.sleep(random.randint(1, 5))

outer(sleep)()	# 调用
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
'
运行
8.2.2 语法糖写法

使用@outer定义在目标函数sleep之上

@outer
def sleep():
	import random
	import time
	print("睡眠中")
	time.sleep(random.randint(1, 5))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

8.3 设计模式

8.3.1 单例模式

创建类的实例后,得到的是完全独立的两个对象,内存地址并不相同。

class Tool:
	pass
t1 = Tool()
t2 = Tool()
print(t1)
print(t2)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
'
运行

某些场景要求,无论获取多少次类对象,都仅提供一个具体的实例,以节省创建类对象的开销和内存开销。

单例模式:保证一个类只有一个实例,并提供一个访问它的全局访问点。

实现模型:在一个文件中定义 → 在另一个文件中导入对象 → 二者对象地址相同,实际为一个对象。

class StrTools:
	pass
str_tool = StrTools()
  • 1
  • 2
  • 3
'
运行
from test import str_tool
s1 = str_tool
s2 = str_tool
print(s1)	# <test.StrToolsobjectat0X0000013D001DB910>
print(s2)	# <test.StrToolsobjectat0X0000013D001DB910>
  • 1
  • 2
  • 3
  • 4
  • 5
8.3.2 工厂模式

当需要大量创建一个类的实例的时候, 可以使用工厂模式。

即从原生的使用类的构造去创建对象的形式迁移到基于工厂提供的方法去创建对象的形式。

class Factory:
	def get_person(self, p_type):
		if p-type = 'w':
			return Worker()
		elif p_type ='s':
			return Student()
		else:
			return Teacher()
factory = Factory()
worker = factory.get_person('w')
stu = factory.get_person('s')
teacher = factory.get_person('t')
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

上图使用工厂类的get_person()方法去创建具体的类对象

优点:

  1. 大批量创建对象的时候有统一的入口,易于代码维护
  2. 当发生修改,仅修改工厂类的创建方法即可
  3. 符合现实世界的模式,即由工厂来制作产品(对象)

8.4 多线程

操作系统中可以运行多个进程,即多任务运行

一个进程内可以运行多个线程,即多线程运行

在这里插入图片描述

  • 进程之间是内存隔离的, 即不同的进程拥有各自的内存空间。
  • 线程之间是内存共享的,线程是属于进程的,一个进程内的多个线程之间是共享这个进程所拥有的内存空间的。

并行执行:同一时间做不同的工作。

进程之间就是并行执行的,操作系统可以同时运行好多程序,这些程序都是在并行执行。除了进程外,线程其实也是可以并行执行的。 — 多线程并行执行

8.4.1 多线编程

Python的多线程可以通过threading模块来实现。

import threading
thread_obj = threading.Thread([group [, target [, name [, args [, kwargs]]]]])
# group:暂时无用,未来功能的预留参数
# target:执行的目标任务名
# args:以元组的方式给执行任务传参
# kwargs:以字典方式给执行任务传参
# name:线程名,一般不用设置
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

启动线程:thread_obj.start()

def sing():
	while True:
		print("我在唱歌,啦啦啦。.。")
		time.sleep(1)
def dance():
	while True:
		print("我在跳舞,哗哗哗哗哗")
		time.sleep(1)

# 多线程运行模式
sing_thread = threading.Thread(target = sing)
dance_thread = threading.Thread(target = dance)
sing_thread.start()
dance_thread.startO)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

8.5 网络编程

socket (简称套接字) 是进程之间通信一个工具,负责进程之间的网络数据传输,好比数据的搬运工。

在这里插入图片描述

Socket服务端:等待其它进程的连接、可接受发来的消息、可以回复消息

Socket客户端:主动连接服务端、可以发送消息、可以接收回复

8.5.1 服务端开发
# 1.创建socket对象
import socket
socket_server = socket.socket()
# 2.绑定socketserver到指定IP和地址
socket_server.bind(host,port)
# 3.服务端开始监听端口
socker_server.listen(backlog)
# back1og为int整数,表示允许的连接数量,超出的会等待
# 可以不填,不填会自动设置一个合理值
# 4.接收客户端连接,获得连接对象
conn,address = socket_server.accept()
printf"接收到客户端连接,连接来自:{address}"# accept方法是阻塞方法,如果没有连接,会卡再当前这一行不向下执行代码
# accept返回的是一个二元元组,可以使用上述形式,用两个变量接收二元元组的2个元素
# 5.客户端连接后,通过recv方法,接收客户端发送的消息
while True:
    data = conn.recv(1024).decode("uTF-8")
    # recv方法的返回值是字节数组(Bytes),可以通过decode使用uTF-8解码为字符串
    # recv方法的传参是buffsize,缓冲区大小,一般设置为1024即可
    if data =='exit':
        break
        print"接收到发送来的数据:",data)
    # 可以通过while True无限循环来持续和客户端进行数据交互
    # 可以通过判定客户端发来的特殊标记,如exit,来退出无限循环
# 6.通过conn(客户端当次连接对象),调用send方法可以回复消息
while True:
    data = conn.recv(1024).decode("uTF-8")
    if data =='exit'break
        print"接收到发送来的数据:",data)
conn.send("你好".encode(UTF-8"))
# 7.conn(客户端当次连接对象)和socketserver对象调用close方法,关闭连接
conn.close()
  • 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
  • 31
  • 32
  • 33
8.5.2 客户端开发
# 1.创建socket对象
import socket
socket_client = socket.socket()
# 2.连接到服务端
socket_client.connect(("localhost",8888))
# 3.发送消息
while True:#可以通过无限循环来确保持续的发送消息给服务端
    send_msg=input"请输入要发送的消息"if send_msg='exit':
        #通过特殊标记来确保可以退出无限循环
        break
    socket_client.send(send_msg.encode("UTF-8"))
    #消息需要编码为字节数组(UTF-8编码)
#4.接收返回消息
whileTrue:
    send_msg=input"请输入要发送的消息".encode("UTF-8")
    socket_client.send(send_msg)
    recv_data =socket_client.recv(1024)#1024是缓冲区大小,一般1024即可
    #recv方法是阻塞式的,即不接收到返回,就卡在这里等待
    print"服务端回复消息为:“,recv_data.decode("UTF-8"))#接受的消息需要通过UTF-8解码为字符串
# 5.关闭链接
socket_client.close()#最后通过close关闭链接

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

8.6 正则表达式

正则表达式(规则表达式,Regular Expression):使用单个字符串来描述、匹配某个句法规则的字符串,常被用来检索、替换那些符合某个模式(规则)的文本。

字符串定义规则,并通过规则去验证字符串是否匹配。

8.6.1 基础匹配

re.match(匹配规则, 被匹配字符串):从被匹配字符串开头进行匹配, 匹配成功返回匹配对象(包含匹配的信息),匹配不成功返回空。

S = 'python itheima python itheima python itheima'
result = re.match('python', s)
print(result) 			# <re.Matchobject; span=(0, 6),match='python'>
print(result.span()) 	# (0, 6)
print(result.group())	# python
  • 1
  • 2
  • 3
  • 4
  • 5

search(匹配规则, 被匹配字符串):搜索整个字符串,找出匹配的。从前向后,找到第一个后,就停止,不会继续向后。

S = '1python666itheima666python666'
result = re.search('python', s)
print(result)	# <re.Matchobject;span=(1, 7),match='python'>
print(result.span())	# (1, 7)
print(result.group())	# python
  • 1
  • 2
  • 3
  • 4
  • 5

findall(匹配规则, 被匹配字符串):匹配整个字符串,找出全部匹配项;找不到返回空list: []

S = '1python666itheima666python666'
result = re.findall('python', s)
print(result)	# ['python', 'python']
  • 1
  • 2
  • 3
8.6.2 元字符匹配
字符功能
.匹配任意一个字符(除了\n),、\.匹配点本身
[]匹配[]中列举的字符
\d匹配数字,即0-9
\D匹配非数字
\s匹配空白,即空格、Tab键
\S匹配非空白
\w匹配单词字符,即a-z、A-Z、0-9、_
\W匹配非单词字符
字符功能
*匹配前一个规则的字符出现0至无数次
+匹配前一个规则的字符出现1至无数次
?匹配前一个规则的字符出现0次或1次
{m}匹配前一个规则的字符出现m次
{m,}匹配前一个规则的字符出现最少m次
{m,n}匹配前一个规则的字符出现m次至n次
字符功能
|匹配左右任意一个表达式
()将括号中字符作为一个分组
字符功能
^
$匹配字符串结尾
\b匹配一个单词的边界
\B匹配非单词边界

案例:

  1. 匹配账号,只能由字母和数字组成,长度限制6到10位,规则为: ^\[0-9a-zA-Z]{6, 10}\$
  2. 匹配QQ号,要求纯数字,长度5-11,第一位不为0,规则为:^\[1-9]\[0-9]{4,10},[1-9]匹配第一位,[0-9]匹配后面4到10位;
  3. 匹配邮箱地址,只允许qq、163、gmail这三种邮箱地址,规则为:^\[\w-]+(\\.\[\w-]+)\*@(qq|163|gmail)(\\.\[\w-]+)+&

8.7 递归

递归: 即方法(函数)自己调用自己的一种特殊编程写法

def func():
	if ...:
		func()
	return ...
  • 1
  • 2
  • 3
  • 4
'
运行

场景:在D:/test 文件夹内,有如下嵌套结构和所属的文件, 可以通过递归编程的形式完成。

在这里插入图片描述

⭐ 需要注意:

  1. 注意退出的条件,否则容易变成无限递归
  2. 注意返回值的传递,确保从最内层,层层传递到最外层
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/919189
推荐阅读
相关标签
  

闽ICP备14008679号