Python基础知识总结
第一章 模块
第一节 Python模块
1.模块的安装
- 利用Python内置的pip工具安装第三方模块
#格式:pip install 模块名
pip install pygame
2.模块的导入和使用
- 导入模块,通过模块调用内容
# 导入格式:import 模块1,模块2,模块3...
import pygame
# 使用方法:模块.函数/模块.变量
import.init()
-
导入模块内容,直接使用
- 部分导入
from pygame import init
init()
- 全部导入
from pygame import *
init()
第二章 Python基础
第一节 代码格式
1.注释
- 单行注释
- 以 ”#“ 开头,代码与注释之间至少应有两个空格
# 这是一个Python单行注释
- 多行注释
- 由3对双引号或单引号包裹的语句
'''
这是一个Python多行注释
使用Print(Print.__doc__)可以获取Python对象的说明文档
'''
2.缩进
- Python语言中不使用” ; "及” { ”,“ } “,以缩进判定语句,同一代码块的每行代码必须拥有相同的缩进量,缩进可以通过“Tab”或空格控制,一般以4个空格表示一级缩进。
- 注:Python3不允许混合使用“Tab”键和空格键
if True:
print("True")
else:
print("False")
3.换行
- 建议每行代码不超过79个字符,Python会将圆括号、中括号和大括号中的行进行隐式连接,故可以在语句外侧添加一对括号实现长语句的换行
string = ("由于语句过长需要换行,这是第一行"
"由于语句过长需要换行,这是第二行"
"由于语句过长需要换行,这是第三行"
"由于语句过长需要换行,这是第四行")
第二节 标识符和关键字
1.标识符
- 标识符应遵守一定的规则:
- 标识符由字母、数字、下划线组成,且不能以数字开头
- 标识符区分大小写
- 不允许使用关键字作为标识符
2.关键字
- 通过查看keyword模块的变量kwlist可查看Python中的关键字
import keyword
print(keyword.kwlist)
第三节 数据类型和变量
1.数据类型
- 数字类型
- 整型(int)
- 浮点型(float)
- 复数类型(complex)
- 布尔类型(bool)
- int的子类,只有True和False两种取值
# 整型: 0 101 -239
# 浮点型: 3.1415 4.2E-10 -2.334E-9
# 复数类型: 3.12+1.2.3j
# 布尔类型: True False
-
字符串
- 字符串是由单引号、双引号或者三引号包裹的有序的字符集合
'Python1234^&' #单引号包裹
"Python3q43EFS" #双引号包裹
'''Pythonasd^&*#$@''' #三引号包裹
-
列表(list)
- 多个元素的集合,可以保存任意数量、任意类型的元素,且可以被修改,使用“ [ ] ”创建列表
[1,2,'hello'] #这是一个列表
- 元组(tuple)
- 可以保存任意数量、任意类型的元素,但不可以被修改,使用“ ( ) ”创建元组
(1,2,'hello') #这是一个元组
- 集合(set)
- 可以保存任意数量、任意类型的元素,区别在于集合使用“ { } ”创建集合,集合中的元素无序且唯一
{1,2,'hello'} #这是一个集合
- 字典(dict)
- 字典中的元素是 “ 键(Key):值(Value)” 形式的键值对,键不能重复,使用“ { } ”创建字典
{"name":"zhangsan","age":18}
- 补充:type()函数——查看变量的类型
print(type(变量名))
2.变量的输入与输出
- input()函数
# 格式:input([prompt])
name = input("请输入您的姓名:")
print(name)
# input()中连接字符串和整型,整数需要转为字符串
input("请输入第"+str[i]+"次:")
- print()函数
- objects:表示输出的对象
- sep:用于设定分隔符,默认使用空格作为分隔符
- end:用于设定输出以什么结尾,默认值为换行符\n
- file:表示数据输出的文件对象
# 格式:print(*objects,sep='',end='\n',file=sys.stdout)
str1='python中'
str2='输出变量'
str3='用print()'
str4='第二行'
print(str1,str2,str3,sep='\n',end=' ')
print(str4)
@Result
python中
输出变量
用print() 第二行
第四节 数字类型
1.整数类型
-
长度没有限制,无需考虑内存溢出
-
四种计数方式
- 二进制(以“0b”或“0B”开头)
- 八进制(以“0o”或“0O”开头)
- 十进制
- 十六进制(以“0x”或“0X”开头)
5 #十进制
0b101 #二进制
0o5 #八进制
0x5 #十六进制
- 进制转换函数
函数 | 说明 |
---|---|
bin(x) | 将x转换为二进制数据 |
oct(x) | 将x转换为八进制数据 |
int(x) | 将x转换为十进制数据 |
hex(x) | 将x转换为十六进制数据 |
2.浮点型
-
Python中浮点型双精度,占8个字节
-
科学计数法
a×10n(1≤|a|<10,n∈N)
-
无穷大(inf)、无穷小(-inf)
3.复数类型
- 复数由实部和虚部组成,一般形式为real+imagj,j为虚部单位
complex_one = 1+2j # 实部为1,虚部为2
print(complex_one.real) # 获取复数实部
print(complex_one.imag) # 获取复数虚部
4.布尔类型
- 特殊的整型,True对应整数1,False对应整数0,Python中常见的布尔值如下:
- None
- False
- 任何数字类型的0,如0、0.0、0j
- 任何空序列,如“”、()、{}
- 空字典,如{}
5.数字类型转换
函数 | 说明 |
---|---|
int(x[,base]) | 将x转换为一个整型数据 |
float(x) | 将x转换为一个浮点型数据 |
complex(x) | 将x转换为复数类型 |
第五节 运算符
1.算术运算符
示例:a=2,b=8
运算符 | 功能说明 | 示例 |
---|---|---|
+ | 加:使两个操作数相加,获取操作数的和 | a+b,结果是10 |
- | 减:使两个操作数相减,获取操作数的差 | a-b,结果是-6 |
* | 乘:使两个操作数相乘,获取操作数的积 | a*b,结果是16 |
/ | 除:使两个操作数相除,获取操作数的商(除数不能为0) | a/b,结果是0.25 |
// | 整除:使两个操作数相除,获取商的整数部分 | a//b,结果是0 |
% | 取余:使两个操作数相除,获取余数 | a%b,结果是2 |
** | 幂:使两个操作数进行幂运算,获取a的b次幂 | a**b,结果是256 |
- (强制)临时类型转换
- 整型与浮点型进行混合运算时,将整型转换为浮点型
- 其他类型与复数类型运算时,将其他类型转换为复数类型
2.赋值运算符
- 允许同时为多个变量赋值
x = y = z =1 # 变量x、y、z均赋值为1
a,b = 1,2 # 变量a赋值为1,变量b赋值为2
- 复合赋值运算符
- Python中没有++和–
运算符 | 功能说明 | 示例 |
---|---|---|
+= | 变量增加指定数值,结果赋值原变量 | num += 2等价于num = num + 2 |
-= | 变量减去指定数值,结果赋值原变量 | num -= 2等价于num = num - 2 |
*= | 变量乘以指定数值,结果赋值原变量 | num *= 2等价于num=num * 2 |
/= | 变量除以指定数值,结果赋值原变量 | num /= 2等价于num=num / 2 |
//= | 变量整除指定数值,结果赋值原变量 | num //= 2等价于num=num // 2 |
%= | 变量进行取余,结果赋值原变量 | num %= 2等价于num=num % 2 |
**= | 变量执行乘方运算,结果赋值原变量 | num **= 2等价于num=num * * 2 |
- (新增)海象运算符
- 用于在表达式内部为变量赋值
num_one = 1
result = num_one + (num_two:=2) # 使用海象运算符为num_two赋值
print(result)
运行结果:3
3.比较运算符
比较运算符包括==、!=、>、<、>=、<=,测试的结果只能是True或False
4.逻辑运算符
逻辑运算符包括 and、or、not(单目)
5.成员运算符
- 判断指定元素是否存在于序列中,存在返回True,否则返回False
x = 'python'
y = 'p'
print(y in x)
print(y not in x)
@Result
True
False
6.位运算符
示例:a = 2,b = 3
运算符 | 功能说明 | 示例 |
---|---|---|
<< | 按位左移 | a<<b,结果为16 |
>> | 按位右移 | a>>b,结果为0 |
& | 按位与运算 | a&b,结果为2 |
| | 按位或运算 | a|b,结果为3 |
^ | 按位异或运算 | a^b,结果为1 |
~ | 按位取反 | ~a,结果为-3 |
- 按位取反是获取数值的补码,然后对补码取反,最后将取反结果转换为原码
- 其余运算均是对其二进制进行运算
7.运算符优先级
运算符 | 描述 |
---|---|
** | 幂(最高优先级) |
*、/、%、// | 乘、除、取模、整除 |
+、- | 加法、减法 |
>>、<< | 按位右移、按位左移 |
& | 按位与 |
^、| | 按位异或、按位或 |
==、!=、>、<、>=、<= | 比较运算符 |
in、not in | 成员运算符 |
not、and、or | 逻辑运算符 |
= | 赋值运算符 |
第三章 流程控制
第一节 条件语句
1.if语句
'''
格式:
if 判断条件:
代码段
'''
score = 88
if score >= 60:
print('考试顺利')
- Python中if语句没有花括号,以冒号结尾,以缩进判断语句是否为if的代码段
2.if-else语句
'''
格式:
if 判断条件:
代码段1
else:
代码段2
'''
score = 88
if score >= 60:
print('考试及格!')
else:
print('考试不及格!')
3.if-elif-else语句
'''
格式:
if 判断条件1:
代码段1
elif 判断条件2:
代码段2
elif 判断条件3:
代码段3
...
else:
代码段n
'''
score = 88
if score >= 85:
print('优秀!')
elif 75 <= score < 85: # Python中可以拼接双判断语句
print('良好')
elif 60 <= score < 75:
print('中等')
else:
print('差')
- 条件语句均可嵌套使用
第二节 循环语句
1.while语句
'''
格式:
while 循环条件:
代码段
'''
i = 1
result = 0
while i <= 10:
result += i # Python中没有++
i += 1
print(result)
2.for语句
'''
格式:
for 临时变量 in 目标对象:
代码段
'''
# Examp1e 1
# 遍历字符串
for word in 'Python':
print(word)
@Result
p
y
t
h
o
n
# Example 2
# range(a):左闭右开区间,以0开始,以a-1结束,每次增进1个步频
for i in range(5):
print(i)
@Result
0
1
2
3
4
# Example 3
# range(a,b):左闭右开区间,以a开始,以b-1结束,每次增进1个步频
for i in range(5,9):
print(i)
@Result
5
6
7
8
# Example 4
# range(a,b,c):左闭右开区间,以a开始,以b-1结束,每次增进c个步频
# 正数
for i in range(0,10,3):
print(i)
@Result
0
3
6
9
# 负数
for i in range(-10,-100,-30):
print(i)
@Result
-10
-40
-70
# Example 5
# 遍历列表(字典、集合同)
s = ['ab','c','d_']
for i in s:
@Result
ab
c
d_
-
循环语句均可嵌套使用
-
for、while后可加else,循环条件为False时执行
for i in range(6):
print(i)
else:
print(i,'=6') # 当循环条件为False,即i = 6时执行
@Result
1
2
3
4
5
i=6
- 循环语句中:
- break:跳出整个循环
- continue:跳出本次循环,开始执行下一个循环,而不会继续执行continue后面的语句
- pass:起到站位作用,仍然会继续往下执行,无任何影响,一般用于使语句完整
第四章 字符串
第一节 字符串及格式化字符串
1.字符串介绍
-
Python中支持单引号、双引号、三引号定义字符串
- 若字符串中包含双引号,则可以使用单引号或三引号包裹(不能嵌套一样的),若包含三引号,则可以使用双引号包裹,以保证解释器按预期对引号匹配
-
转义字符
转义字符 | 功能说明 |
---|---|
\b | 退格 |
\n | 换行 |
\v | 纵向制表符 |
\t | 横向制表符 |
\r | 回车 |
- 原始字符串
- 如果字符串中包含转义字符并不希望其产生作用,此时可以使用原视字符串,即在字符串开始的引号之前添加r或R
print(r'转义字符中:\n表示换行;\r表示回车;\b表示退格')
@Result
转义字符中:\n表示换行;\r表示回车;\b表示退格
2.格式化字符串
-
使用**%**格式化
-
常见格式符
%c、%s、%u、%d、%o、%x、%f
-
格式及使用
-
# format % values
name = '张倩'
age = 27
address = '北京市昌平区'
print('-----------------------')
print("姓名:%s"%name)
print("年龄:%d岁\n家庭住址:%s"%(age,address))
print('-----------------------')
@Result
-----------------------
姓名:张倩
年龄:27岁
家庭住址:北京市昌平区
-----------------------
- 使用format()方法格式化
- 格式及应用
# str.format(values) str中包含若干为真实数据占位的{},values为代替换的真实数据,format格式化无需关注数据类型
# Example 1
# 常规格式化
name = '张倩'
age = 26
string = '姓名:{}\n年龄:{}'
print(string.format(name,age))
@Result
姓名:张倩
年龄:26
# Example 2
# 指定编号格式化,索引从0开始
name = '张倩'
age = 26
string = '姓名:{1}\n年龄:{0}'
print(string.format(age,name))
@Result
姓名:张倩
年龄:26
# Example 3
# 指定名称初始化,Python解释器自动绑定真实数据
name = '张倩'
age = 26
weight = 65
string = '姓名:{name}\n年龄:{age}\n体重:{weight}kg'
print(string.format(age=age,name=name,weight=weight))
@Result
姓名:张倩
年龄:26
体重:65kg
# Example 4
# 精度格式化(浮点型数据)
import math
# print('{:.2%}'.format(math.PI)) {:.2%}为转化成保留两位小数的百分比
print('{:+10.2f}'.format(math.PI))
@Result
3.14
- 使用f-string格式化
- f或F引领字符串,字符串中使用 ‘ {变量名} ’ 为真实数据占位
- 格式及应用
# f'{变量名}'或F'{变量名}'
age = 20
gender = '男'
print(f'年龄:{age},性别:{gender}')
@Result
年龄:20,性别:男
3.字符串的常见操作
- 字符串查找
- 查找字符串中是否包含字串,包含返回首次出现的位置,否则返回**-1**
- 格式及应用
# str.find(sub[,start[,end]])
sub:指定查找的字串
start:开始索引,默认为0
end:结束索引,默认为字符串的位置
word = 't'
string = 'Python'
res = string.find(word)
print(res)
@Result
2 #下标以0开始
- 字符串替换
- 格式及应用
# str.replace(old,new[,count])
old:被替换的子串
new:替换旧子串的新子串
count:表示替换旧字符串的次数,默认全部替换
string = 'He said,"you have to go forward,Then turn left,Then go forward,and Then turn right."'
new_string = string.replace("Then","then",2) #指定替换2次
print(new_string)
@Result
He said,"you have to go forward,then turn left,then go forward,and Then turn right"
- 字符串分割
- 返回由分割后字串组成的列表
# str.split(sep=None,maxsplit=-1)
sep:分隔符,默认为空字符
maxsplit:分割次数,默认值为-1,表示不限制分割次数
string_example = 'The more efforts you make,the more fortune you get.'
print(string_example.split()) # 以空格作为分隔符
print(string_example.split('m')) # 以字母m作为分隔符
print(string_example.split('e',2)) # 以字母e作为分隔符,并分割两次
@Result
['The','more','efforts','you','make','the','more','fortune','you','get.']
['The','ore efforts you','ake,the','ore fortune you get.']
['Th','mor','efforts you make,the more fortune you get.']
- 删除字符串指定字符
方法 | 语法格式 | 功能说明 |
---|---|---|
strip ( ) | str.strip([chars]) | 移除字符串头部和尾部的指定字符 |
lstrip ( ) | str.lstrip([chars]) | 移除字符串头部的指定字符 |
rstrip ( ) | str.rstrip([chars]) | 移除字符串尾部的指定字符 |
- 字符串大小写转换
方法 | 功能说明 |
---|---|
upper ( ) | 将字符串中小写字母转大写字母 |
lower ( ) | 将字符串中大写字母转小写字母 |
capitalize ( ) | 将字符串中第一个字母转换成大写形式 |
title ( ) | 将字符串中每个单词首字母转换成大写形式 |
- 字符串对齐
- 如果width小于字符串长度,返回原字符串
- fillchar为对齐填充字符,默认为空格
方法 | 语法格式 | 功能说明 |
---|---|---|
center ( ) | str.center(width[,fillchar]) | 返回长度为width的字符串,原字符串居中显示 |
ljust ( ) | str.ljust(width[,fillchar]) | 返回长度为width的字符串,原字符串左对齐显示 |
rjust ( ) | str.rjust(width[,fillchar]) | 返回长度为width的字符串,原字符串右对齐显示 |
sentence = 'hello world'
ljust = sentence.ljust(13,'-');
print(f"左对齐显示:{ljust}")
@Result
hello world--
- 截取字符串
- 左闭右开区间
- 变量[头下标:尾下标]
- 支持双向索引
例:str = ‘RUNOOB’
-6 -5 -4 -3 -2 -1
R | U | N | O | O | B |
---|
0 1 2 3 4 5
str[0] = 'R'
str[3] = '0'
str[:] = 'RUNOOB'
str[0:] = 'RUNOOB'
str[:3] = 'RUN'
str[1:4] = 'UNO'
str[-4:-2] = 'OO'
-
列表转为字符串——join()
string.join(iterable) #
string
指的是所需的分隔符
flexiple = ["Hire", "the", "top", "freelancers"]
print(" ".join(flexiple))
# join仅处理字符串,对于某些处理的可迭代对象包含int值时,可以使用" ".join(map(str,flexiple))
- 其它
方法 | 语法格式 | 功能说明 |
---|---|---|
isdigit ( ) | str.isdigit ( ) | 判断字符串是否由数字组成,是返回True |
isalpha ( ) | str.isalpha ( ) | 判断字符串是否由数字组成,是返回True |
isalnum ( ) | str.isalnum ( ) | 判断字符串是否由数字组成,是返回True |
len ( ) | str.len ( ) | 返回字符串的长度 |
* | str*3 | str=‘UN’ , str*3 =‘UNUNUN’ |
第五章 组合数据类型
第一节 认识组合数据类型
1.序列类型
-
在数列基础上进行拓展,序列支持双向索引(同截取字符串)
-
常见的序列类型:字符串(str)、列表(list)、元组(tuple)
2.集合类型
- 集合元素3个特征
- 确定性
- 互异性
- 无序性:若多个集合中元素仅顺序不同,那么这些集合本质上是同一集合
- Python中要求放入集合的元素必须是不可变类型
- 不可变类型:整型、浮点型、字符串类型、元组(前三者理论不可变,改变后原则上已不是原先的变量)
- 可变类型:列表、字典、集合
3.映射类型
- 字典(dict)是Python中唯一的内置映射类型,遵守以下两个原则:
- 每个键只能对应一个值,不允许同一个键在字典中重复出现
- 字典中的键是不可变类型
第二节 列表(list)
1.创建列表
- 使用中括号“ [ ] ”创建列表
- 列表元素可以是各种类型的组合,列表中的元素用“ , ”分隔
li_one = [] # 创建空列表
li_two = [1,'a','%$',2.6,li_one,"Python"] # 列表中内嵌了一个列表
-
使用list ( )函数创建列表、将字符串、元组、字典转列表
-
list ( ) 接收一个可迭代类型的数据,返回一个列表
- 可迭代类型:可遍历的类型,可用isinstance ( ) 函数判断是否为可迭代类型
from collections.abc import Iterable Is = [3,4,5] print(isinstance(Is,Iterable)) @Result True
-
li_one = list(1) # 创建失败,1不是可迭代类型
li_two = list([1,'a','%$',2.6,"Python"]) # 列表类型是可迭代类型
dict_one = {'A':55,'B':'52','C':'python'}
li_three = list(dict_one.values()) # .values将会把字典中的值转换为列表,如果使用字典名,会将键转换为列表
print(li_two)
print(dict_one)
print(li_three)
@Result
[1, 'a', '%$', 2.6, 'Python']
{'A': 55, 'B': '52', 'C': 'python'}
[55, '52', 'python']
2.访问列表元素
- 索引的方式访问
- 对于列表内嵌套元素的二次访问,以多维数组的访问形式进行
- 支持双向索引
# 格式:list[n]/list[m][n][k]...
li_one = list([1,'a','%$',2.6,['Python','c++']])
print(li_one[2]) # 访问下标为2的元素
print(li_one[4][1]) # 访问下标为4元素中下标为1的元素
print(li_one[4][0][2]) # 访问下标为4元素中下标为0元素中下标为2的元素
@Result
%$
c++
t
- 切片的形式访问(左闭右开)
- 如果要将一个列表赋值给另一个列表,使用li1 = li2是直接将地址指向,修改li2的值li1也会随之更改,如果仅仅只是赋值,可以使用切片形式li1 = li2[:]
# 格式:list[m:n:step]
m:索引起始位置,可省略,表示从列表首部开始
n:索引结束位置,可省略,表示到列表尾部结束
step:步长,默认为1
li_one = ['p','y','t','h','o','n']
print(li_one[1:4:2])
print(li_one[2:])
print(li_one[:3])
print(li_one[:])
@Result
['y', 'h']
['t', 'h', 'o', 'n']
['p', 'y', 't']
['p', 'y', 't', 'h', 'o', 'n']
- 在循环中依次访问
li_one = ['p','y','t','h','o','n']
for li in li_one:
print(li,end=' ')
@Result
p y t h o n
3.添加列表元素
- append ( ) 方法
- 列表尾部添加新元素
li_one = ['p','y','t','h','o']
li_one.append('n')
print(li_one)
@Result
['p', 'y', 't', 'h', 'o', 'n']
- extend ( ) 方法
- 在列表尾部一次性添加另一个列表中所有元素
li_one = ['p','y','t','h','o','n']
li_two = ['j','a','v','a']
li_one.extend(li_two)
print(li_one)
@Result
['p', 'y', 't', 'h', 'o', 'n', 'j', 'a', 'v', 'a']
- insert ( ) 方法
- 按照索引将新元素插入(索引以0开始)
li_one = ['p','y','h','o','n']
li_one.insert(2,'t')
print(li_one)
@Result
['p', 'y', 't', 'h', 'o', 'n']
4.元素排序
- sort ( ) 方法
- 覆盖原列表元素
# sort(key=None,reverse=False)
key:指定排序规则
reverse:元素排序的方式,True为降序,False(默认)为升序
li_one = [6,2,5,3]
li_two = [7,3,5,4]
li_three = ['python','java','php']
li_one.sort()
li_two.sort(reverse=True)
li_three.sort(key=len) # len()函数可计算字符串的长度,按照列表中每个字符串元素的长度排序
print(li_one)
print(li_two)
print(li_three)
@Result
[2, 3, 5, 6]
[7, 5, 4, 3]
['php', 'java', 'python']
- sorted ( ) 方法
- 按升序排列元素
- reverse ( )
- 逆置列表,原列表元素从右至左依次排列存放
5.删除列表元素
- del语句
- 删除指定元素或整个列表
li = ['python','java','php']
del li[0] # 删除指定元素
print(li)
del li # 删除列表
print(li)
@Result
['java', 'php']
Traceback (most recent call last):
File "C:\Users\清明\Desktop\12.py", line 5, in <module>
print(li)
NameError: name 'li' is not defined
- remove ( ) 方法
- 移除列表中某个元素,若列表中有多个匹配的元素,只移除第一个
li = ['python','java','php']
li.remove('python')
print(li)
@Result
['java', 'php']
- pop ( ) 方法
- 移除指定元素,若未指定,移除列表末尾元素
li = [1,2,3,4,5]
print(li.pop()) # 移除列表末尾元素
print(li.pop(1)) # 移除列表索引为1的元素
print(li)
@Result
5
2
[1, 3, 4]
- clear ( ) 方法
- 清空列表(非删除)
li = [1,2,3,4,5]
li.clear()
print(li)
@Result
[]
6.列表推导式
- 基本格式
[exp for x in list]
- 带if语句的列表推导式
[exp for x in list if cond]
- 嵌套for循环语句的列表推导式
[exp for x in list_1 for y in list_2]
- 带有if语句和嵌套for循环语句的列表推导式
[exp for x in list_1 [if cond_1]
for y in list_2 [if cond_2]
...
for n in list_3 [if cond_3]]
- 应用
li_one = [1,2,3]
li_two = [4,5,6]
li_three = [x+y for x in li_one for y in li_two]
print(li_three)
@Result
[5, 6, 7, 6, 7, 8, 7, 8, 9]
7.最值与求和
max()取最大值
min()取最小值
sum()求和
使用前提:列表中元素类型为整型
第三节 元组(tuple)
1.创建元组
- 以“ ( ) ”创建,元素用“ , ”分隔,元组中元素个数、类型不受限制,元素不可修改,元组属于不可变类型
t1 = () # 空元组
t2 = (1,) # 包含单个元素的元组
t3 = (1,2,3) # 包含多个元素的元组
t4 = (1,'c','e',('a','d')) # 元组嵌套
- 以tuple ( ) 函数创建
t1 = tuple() # 创建空元组
t2 = tuple([1,2,3]) # 利用列表创建元组(1,2,3)
t3 = tuple('python') # 利用字符串创建元组('p','y','t','h','o','n')
t4 = tuple(range(5)) # 利用可迭代对象创建元组(0,1,2,3,4)
2.访问元组元素
- Python支持索引和切片访问元组的元素,也支持循环中遍历元组
print(t2[1]) # 以索引方式访问元组元素
print(t3[2:5]) # 以切片方式访问元组元素
for data in t3: # 在循环中遍历元组
print(data,end='')
@Result
2
('t','h','o')
p y t h o n
第四节 集合
1.创建集合
- 以“ { } ”创建,元素用“ , ”分隔,集合中元素个数、类型不受限制,元素可修改,元组属于可变类型,“ { } ”不能创建空集合(不包含元素的“ { } ”创建的是空字典),空集合只能通过set( )创建
s1 = {1} # 单元素集合
s2 = {1,'b',(2,5)} # 多元素集合
- 以set ( ) 函数创建,set ( ) 函数可以创建空集合
s1 = set([1,2,3])
s2 = set((2,3,4))
s3 = set('python')
s4 = set(range(5))
2.集合的常见操作
常见方法 | 说明 |
---|---|
add(x) | 向集合中添加元素x,x已存在时不做处理 |
remove(x) | 删除集合中元素x,若x不存在则抛出KeyError异常 |
discard(x) | 删除集合中的元素x,若x不存在不做处理 |
pop() | 随机返回集合中的一个元素,同时删除该元素;若集合为空,抛出KeyError异常 |
clear() | 清空集合 |
copy() | 复制集合,返回值为集合 |
isdisjoint(T) | 判断集合与集合T是否没有相同的元素,没有返回True,有则返回False |
s1.add('s')
s2.remove(3)
s3.discard('p')
data = s4.pop()
s3.clear()
s5 = s2.copy()
s4.isdisjoint(s2)
3.集合推导式
- 集合推导式与列表推导式相似,区别在于集合推导式外侧为‘ { } ’
# 格式
{exp for x in set if cond}
第五节 字典
1.创建字典
- 字典表现为一组包含在‘ { } ’中的键值对,每个键值为一个字典元素,元素之间通过逗号‘ , ’分隔,每对键值之间通过‘ : ’分隔。值可以是任意类型,键不能是列表或字典类型。字典元素无序,键/值必须唯一。
d1 = {} # 创建空字典
d2 = {'A':'123','B':'35','C':'786'}
d3 = {'A':123,12:'C'}
- 以dict ( ) 函数创建
d4 = dict() # 创建空字典
d5 = dict({'A':123,12:'C'}) # 创建非空字典
2.字典的访问
- 利用键访问
print(d2['A'])
print(d3[12])
- 利用内置方法get ( ) 根据键从字典中获取对应的值,若指定的键不存在则返回默认值
# 格式
d.get(key[,default])
print(d2.get('A'))
print(d3.get(13,-1))
@Result
123
-1 # d3中不存在13的键,返回默认值-1
- 字典设计的数据分为键、值、元素(键值对),Python提供了用于访问字典中所有键、值和元素的内置方法keys()、values()和items(),其返回值都是可迭代对象,利用循环可以遍历这些返回值(遍历时不能修改元素)
dic = {'name':'Jack','age':23,'height':185}
print(dic.keys()) # 利用keys()方法获取所有键
print(dic.values()) # 利用values()方法获取所有值
print(dic.items()) # 利用items()方法获取所有元素
for key in dic.keys():
print(key)
@Result
dict_keys(['name', 'age', 'height'])
dict_values(['Jack', 23, 185])
dict_items([('name', 'Jack'), ('age', 23), ('height', 185)])
name
age
height
3.字典元素的添加和修改
- 字典元素的添加
# 格式
1.为指定键赋值
字典变量[键] = 值
2.update()方法
字典变量.update(键=值)
add_dict = {'name':'Jack','age':23,"height":185}
add_dict["sco"] = 98
add_dict.update(weight = 50)
print(add_dict)
@Result
{'name': 'Jack', 'age': 23, 'height': 185, 'sco': 98, 'weight': 50}
-
字典元素的修改
字典元素的修改与元素的添加同理,实质上是对元素的重新赋值
add_dict = {'name': 'Jack', 'age': 23, 'height': 185, 'sco': 98, 'weight': 50}
add_dict["sco"] = 60
add_dict.update(weight = 100)
print(add_dict)
@Result
{'name': 'Jack', 'age': 23, 'height': 185, 'sco': 60, 'weight': 100}
4.字典元素的删除
-
pop()删除指定元素
根据指定键删除字典中的元素,删除成功返回目标元素的值
dic = {'001': '张三', '002': '李四', '003': '王五', '004': '赵六'}
print(dic.pop('001')) # 删除指定键为001的元素
print(dic)
@Result
张三
{'002': '李四', '003': '王五', '004': '赵六'}
-
popitem()删除随机元素
随机删除字典中的元素,之所以能随机,因为字典元素本身无序,没有首项尾项之分
dic = {'001': '张三', '002': '李四', '003': '王五', '004': '赵六'}
print(dic.popitem())
print(dic)
@Result
('004', '赵6六')
{'001': '张三', '002': '李四', '003': '王五'}
-
clear()清空字典
清空字典中的元素
dic = {'001': '张三', '002': '李四', '003': '王五', '004': '赵六'}
dic.clear()
print(dic)
@Result
{}
5.字典推导式
- 字典推导式与列表推导式相似,区别在于字典推导式外侧为‘ { } ’,且内部需包含键和值两个部分
# 格式
{new_key:new_value for key,value in dict.items}
eg.快速交换键值对
{new_value:new_key for key,value in dict.items}
第六节 组合数据类型应用运算符
某些对数字类型的运算符对组合数据类型同样适用,本处主要介绍+、*、in、not in对组合数据类型进行运算时的规则
1.“+”运算符
- 与数字类型不同,组合数据类型相加不进行数值的累加,而是进行数据的拼接
str_one = "hello "
str_two = "world"
print(str_one + str_two)
list_one = [1,2,3]
list_two = [4,5,6]
print(list_one + list_two)
tuple_one = (1,2,3)
tuple_two = (4,5,6)
print(tuple_one + tuple_two)
@Result
hello world
[1, 2, 3, 4, 5, 6]
(1, 2, 3, 4, 5, 6)
2.“*”运算符
- “*”运算符运算之后产生的结果为与原数据整数倍的拼接
list_one = [1,2,3]
print(list_one * 3)
@Result
[1, 2, 3, 1, 2, 3, 1, 2, 3]
3.“in”、“not in”运算符
- 用于判断某个元素是否属于某个变量,存在返回True,不存在返回False
list_one = [1,2,3]
print(1 in list_one)
print(1 not in list_one)
@Result
True
False
第六章 函数
第一节 函数的定义和调用
1.定义函数
- 格式
def 函数名([参数列表]):
['''文档字符串''']
函数体
[return 语句]
- 嵌套定义函数(类似局部变量,仅在外层函数内有效)
def add(a,b): # 外层函数
print(a+b)
def mul(c,d): # 定义内层函数,仅在外层函数可调用
return c*d
mul = mul(a,b) # 调用内层函数
print(mul)
2.调用函数
- 格式
函数名([参数列表])
- 函数可嵌套调用
3.函数参数传递
- 位置参数传递
- 按照参数的前后位置依次传递参数
- 关键字参数传递
- 通过 “ 形参 = 实参 ” 的格式将实参、形参相关联
def connect(ip,port):
print(f'设备{ip}:{port}连接!')
connect(ip='127.0.0.1',port='8080') # 按关键字参数的方式传递实参
@Result
设备127.0.0.1:8080连接!
- 如何区分位置参数、关键字参数
- ‘’ / ‘’ 限定部分形参只接收采用位置参数传递方式
def func(a,b,/,c): # / 指明前面的参数a、b均为仅限位置形参
print(a,b,c)
# 错误的调用方式
# func(a=10,20,30)
# func(10,b=20,30)
# 正确的调用方式
func(10,20,c=30)
func(10,20,30)
@Result
10 20 30
10 20 30
- 默认参数的传递
def connect(ip,port=8080):
print(f'设备{ip}:{port}连接!')
# 调用1
connect(ip="127.0.0.1")
# 调用1
connect(ip="127.0.0.1",port=3306)
@Result
设备127.0.0.1:8080连接!
设备127.0.0.1:3306连接!
4.参数的打包与解包
- 打包
- 参数前加 ‘ * ’ ,可以接收以元组形式打包的多个值
- 参数前加 ‘ ** ’ ,可以接收以字典形式打包的多个值
# 元组打包
def test(*args): # 参数前加 ‘ * ’ ,可以接收以元组形式打包的多个值
print(args)
test(11,22,33,44,55) # 以元组形式输出
@Result
(11, 22, 33, 44, 55)
# 字典打包
def test(**args): # 参数前加 ‘ ** ’ ,可以接收以字典形式打包的多个值
print(args)
test(a=11,b=22,c=33,d=44,e=55) # 以字典形式输出
@Result
{'a': 11, 'b': 22, 'c': 33, 'd': 44, 'e': 55}
- 解包
- 如果接收的实参是元组类型的数据,可以使用 ‘ * ’ 将元组拆分成多个值,按照位置参数传递的方式赋给形参
- 如果接收的实参是字典类型的数据,可以使用 ‘ ** ’ 将字典拆分成多个值,按照关键字参数传递的方式赋给形参
def test(a,b,c,d,e):
print(a,b,c,d,e)
nums = (11,22,33,44,55) # 元组解包
test(*nums)
nums0 = {'a':11,'b':22,'c':33,'d':44,'e':55} # 字典解包
test(**nums0)
@Result
11 22 33 44 55
11 22 33 44 55
5.混合传递
- 优先级为:按位置参数传递、按关键字参数传递、默认参数传递、按打包传递,带默认值的参数必须于普通参数之后,带*的参数必须位于带默认值的参数之后,带**的参数必须位于带 * 的参数之后
def test(a,b,c=33,*args,**kwargs):
print(a,b,c,args,kwargs)
test(1,2)
test(1,2,3)
test(1,2,3,4)
test(1,2,3,4,e=5)
@Result
1 2 33 () {}
1 2 3 () {}
1 2 3 (4,) {}
1 2 3 (4,) {'e': 5}
6.函数的返回值
- 只返回一个值正常返回;返回多个值,这些值将被保存到元组中
第七章 文件
第一节 文件概述
1.文件标识分为路径、文件名主干、拓展名3部分
D:\incast\chapter10</u> example .dat
路径 文件主干 拓展名
os.path.splitext(path)[-1]可获取文件后缀
2.按照逻辑存储结构,文件可分为二进制文件和文本文件
- 文本文件:无除文本字符外的其他数据,可以直接用文字处理程序(如记事本)打开
- 二进制文件:图像、视频、音频、数据库、可执行文件等都属于二进制文件,必须用管理程序才能正确获取文件信息
3.标准文件
Python的sys模块定义了3个标准文件,分别为stdin(标准输入文件,对应输入设备,如键盘),stdout(标准输出文件,对应输出设备,如显示器),stderr(标准错误文件,同stdout,对应输出设备)
import sys
file = sys.stdout
file.write("hello world") # 写入标准输出文件,即打印到终端
@Result
hello world
第二节 文件的基本操作
1.文件的打开与关闭
- 打开文件(mode、encoding见本节末尾)
open(file,mode=‘r’,encoding=None)
file代表文件路径
mode代表文件打开模式
encoding指定文件编码格式
file = open("D:\\文件\\3+4\\计算3+4 各活动名单.txt",'r') # 以只读方式打开D盘下的txt文件
file1 = open("a.txt") # 打开当前目录的文本文件a.txt
@Result # a.txt文件不存在报FileNotFoundError异常
Traceback (most recent call last):
File "D:\Program Files (x86)\Tencent\QQ\12.py", line 2, in <module>
file1 = open("a.txt") # 打开当前目录的文本文件a.txt
FileNotFoundError: [Errno 2] No such file or directory: 'a.txt'
常用文件打开模式及其搭配
打开模式 | 名称 | 描述 |
---|---|---|
r/rb | 只读模式 | 以只读方式打开文本文件/二进制文件,若文件不存在,文件打开失败 |
w/wb | 只写模式 | 以只写方式打开文本文件/二进制文件,若文件已存在,则重写文件,否则创建新文件 |
a/ab | 追加模式 | 以追加方式打开文本文件/二进制文件,只允许在该文件末尾追加数据,否则创建新文件 |
r+/rb+ | 读取(更新)模式 | 以读/写方式打开文本文件/二进制文件,若文件不存在,文件打开失败 |
w+/wb+ | 写入(更新)模式 | 以读/写方式打开文本文件/二进制文件,若文件已存在,则重写文件 |
a+/ab+ | 追加(更新)模式 | 以读/写方式打开文本文件/二进制文件,只允许在该文件末尾追加数据,否则创建新文件 |
常用编码方式及字符与字节的对应关系
编码格式 | 语言 | 字符数 | 字节数 |
---|---|---|---|
ASCII | 中文 | 1 | 2 |
英文 | 1 | 1 | |
UTF-8 | 中文 | 1 | 3 |
英文 | 1 | 1 | |
Unicode | 中文 | 1 | 2 |
英文 | 1 | 2 | |
GBK | 中文 | 1 | 2 |
英文 | 1 | 1 |
-
关闭文件
- close()方法手动关闭(建议)
file.close()
- **with()**语句预定义清理操作,实现文件的自动关闭
with open(a.txt) as f: pass # 文件操作
2.文件的读写
-
写文件(覆盖文件原内容)
-
write()方法
write(data) # data为字符串
string = "Hello world" with open("file_write.txt",mode="w",encoding='utf-8') as f: print(f.write(string)) # 将字符串写入文件并输出返回的字节数(writelines不可用,返回值None) @Result 11
-
-
writelines()方法
writelines(data) # data为字符串或字符串列表
# 若要在文件中进行换行,应显式指定换行符 \n string = "Hello world\nI'm Python" with open("file_write.txt",mode="w",encoding='utf-8') as f: f.writelines(string)
-
读文件
-
read()方法
read(n=-1) # n设置读取数据的字节数,若缺省,读取剩余的全部数据
with open("file_write.txt",mode="r",encoding='utf-8') as f: print(f.read(2)) # 读取两个字节的数据 print(f.read()) # 读取剩余数据 @Result He llo world
-
readline()方法
randline() # 从指定文件中读取一行数据,若添加了参数,作用等同于read()
with open("file_write.txt",mode="r",encoding='utf-8') as f: print(f.readline()) @Result Hello world
-
readlines()方法
randlines(hint=-1) # 一次性读取指定文件中所有数据,hint控制要读取的行数,如果行中数据的总大小超出了hint字节,方法不会继续读取更多的行
with open("file_write.txt",mode="r",encoding='utf-8') as f: print(f.readlines(5)) @Result ['Hello world\n'] # 输出格式为列表,\n会被显式输出
-
第八章 面向对象
第一节 类与对象的基础应用
1.类的定义
- 类包含类特征的数据成员,以及描述类行为的成员函数,其中数据成员称为属性,成员函数称为方法
class 类名:
属性名 = 属性值 # 定义属性
def 方法名(self): # 定义方法,self必须有,但无须为其传参
方法体
2.对象的创建和调用
- 创建对象
# 对象名 = 类名()
car = Car()
- 对象的使用
对象名.属性名
对象名.方法名()
第二节 类的成员
-
属性
按声明方式分为两类:类属性、实例属性
- 类属性
- 声明在类内部、方法外部的属性
- 可以通过类或对象进行访问
- 只能通过类修改
class Car: w = 4 def driver(self): print('类方法') car = Car() car.driver() print(car.w) print(Car.w) Car.w = 5 print(car.w) print(Car.w) car.w = 6 # 动态添加了一个实例属性 print(car.w) # 访问的是新增的实例属性 print(Car.w) # 访问的是原来的类属性 @Result 类方法 4 4 5 5 6 5
- 实例属性
- 在方法内部声明的属性
- 只能通过对象访问
- 通过对象进行修改
- 动态添加实例属性
class Car: def driver(self): self.wheels = 4 # 添加实例属性时需要加self.,加了后无法使用Car.wheels访问 car = Car() car.driver() # 产生实例对象 print(car.wheels) print(Car.wheels) # 无法使用类名访问 car.color = "red" # 动态添加实例属性color print(car.color) @Result 4 red Traceback (most recent call last): File "D:\Program Files (x86)\Tencent\QQ\12.py", line 8, in <module> print(Car.wheels) AttributeError: type object 'Car' has no attribute 'wheels'
- 类属性
-
方法
按照定义方式和用途可分为:实例方法、类方法、静态方法
- 实例方法
- 定义在类内部、以self为第一个形参
- 只能通过对象调用
class Car: def driver(self): print("我是实例方法") car = Car() car.driver() # 对象调用实例方法 Car.driver() # 类调用实例方法 @Result 我是实例方法 Traceback (most recent call last): File "D:\Program Files (x86)\Tencent\QQ\12.py", line 7, in <module> Car.driver() # 类调用实例方法 TypeError: driver() missing 1 required positional argument: 'self'
-
类方法
-
定义在类内部、使用装饰器**@classmethod**修饰
-
参数列表第一个参数为cls,代表类本身
@classmethod
def 类方法名(cls):
方法体
-
class Car: @classmethod def stop(cls): print('我是类方法') car = Car() car.stop() Car.stop() @Result 我是类方法 我是类方法
- 可以使用cls访问和修改类属性的值
- 实例方法
class Car:
wheels = 3 # 类属性
@classmethod
def stop(cls): # 类方法
print(cls.wheels) # 使用cls访问类属性
cls.wheels = 4 # 使用cls修改类属性
print(cls.wheels)
car = Car()
car.stop()
@Result
3
4
- 静态方法
- 定义在类内部,使用装饰器@staticmethod修饰
>@staticmethod
>def 静态方法名():
> 方法体
- 没有默认参数,适用于与类无关的操作
- 通过类和对象调用
```python
class Car:
@staticmethod
def test(): # 静态方法
print('我是静态方法')
car = Car()
car.test() # 通过对象调用静态方法
Car.test() # 通过类调用静态方法
@Result
我是静态方法
我是静态方法
```
- 内部不能直接访问属性或方法,使用类名访问类属性或调用类方法
```python
class Car:
wheels = 3
@staticmethod
def test():
print('我是静态方法')
print(f'类属性的值是{Car.wheels}') # 静态方法中访问类属性
car = Car()
car.test
@Result
我是静态方法
类属性的值是3
```
- 私有成员
- Python 中成员默认是**公有成员**,在其前加**双下划线**即可成为私有成员
- 私有成员的访问
- 类的**内部**直接访问,外部无法访问
- 类的外部通过调用类的公有方法的方式进行访问
```python
class Car:
__wheels = 4 # 私有属性
def __driver(self): # 私有方法
print('行驶')
def test(self):
print(f'轿车有{self.__wheels}个车轮') # 类内部公有方法访问私有属性
self.__driver() # 类内部公有方法访问私有方法
car = Car()
car.test()
print(car.wheels) # 类外部访问私有属性
car.__driver # 类内部访问私有属性
class Test():
count = 21
def change(self):
count = 20 # 新建一个count属性,类似于局部变量
self.count += 20 # self.count初始值为类属性,即21
print(count) # 输出count(没有self为局部变量),值为20
print(self.count) # 输出实例属性count,运算后为41
test = Test()
test.change()
print(Test.count) # 输出类属性,值为21
print(test.count) # 输出实例属性count,值为41
@Result
20
41
21
41
第三节 特殊方法
-
构造方法
每个类都有一个默认隐式的构造方法_ init _(),如果定义了显式构造方法,则使用显式方法,否则使用默认方法
- 有参构造方法
- 无参构造方法
class Car:
def __init__(self): # 无参构造方法
self.color="红色"
def drive(self):
print(f'车的颜色为{self.color}')
car1 = Car()
car1.drive()
car2 = Car()
car2.drive()
@Result
车的颜色为红色
车的颜色为红色
class Car:
def __init__(self,color): # 有参构造方法
self.color = color
def drive(self):
print(f'车的颜色为{self.color}')
car1 = Car('红色') # 根据实参初始化属性
car1.drive()
car2 = Car('蓝色') # 根据实参初始化属性
car2.drive()
@Result
车的颜色为红色
车的颜色为蓝色
-
析构方法
每个类都有一个默认隐式的析构方法_ del _(),如果定义了显式析构方法,则使用显式方法,否则使用默认方法
class Car:
def __init__(self):
self.color = '红色'
print('对象被创建')
def __del__(self):
print('对象被销毁')
car = Car()
print(car.color)
del car
print(car.color)
@Result
对象被创建
红色
对象被销毁
Traceback (most recent call last):
File "D:\Program Files (x86)\Tencent\QQ\12.py", line 12, in <module>
print(car.color)
NameError: name 'car' is not defined
第四节 封装
- 封装是面向对象的重要特性之一
- 基本思想是:对外隐藏类的细节,提供用于访问类成员的公开接口。类的外部无须知道类的实现细节,只需要使用公开接口便可访问类的内容
class Person:
def __init__(self,name):
self.name = name # 姓名
self.__age = 1 # 年龄,默认为1岁,私有属性
# 设置私有属性值的方法
def set_age(self,new_age):
if 0 < new_age <=120: # 判断年龄是否合法,new_age为外部传来的值,不需要self
self.__age = new_age
# 获取私有属性值的方法
def get_age(self):
return self.__age
# 获取私有属性值的方法
def get_name(self):
return self.name
person = Person('小明')
person.set_age(20)
print(f'{person.get_name()}年龄为{person.get_age()}岁')
@Result
小明年龄为20岁
第五节 继承
-
类与类之间具有继承关系,被继承的类称为父类或基类,继承其他类的类称为子类或派生类,子类会自动拥有父类的公有成员
-
继承分为单继承、多继承
-
继承的父类中有重名方法,按顺序来,执行先继承的父类的方法
# 定义一个表示房屋的类House
class House(object):
def live(self):
print('供人居住')
# 定义一个表示汽车的类Car
class Car(object):
def drive(self):
print('行驶')
# 单继承,定义一个类,继承Car类
class RedCar(Car):
def color(self): # 子类中定义新方法
print('红车')
# 多继承,定义一个表示房车的类,继承House类和Car类
class TouringCar(House,Car):
pass
red_car = RedCar()
red_car.drive() # 调用父类的方法
red_car.color() # 调用子类新定义的方法
tour_car = TouringCar()
tour_car.live() # 子类对象调用父类的House方法
tour_car.drive() # 子类对象调用父类的Car方法
@Result
行驶
红车
供人居住
行驶
- 调用父类方法&调用父类构造方法初始化
super(Class,class).method()
Class为继承语句行中,方法所在类左边的类名
class People:
def __init__(self,name,age,weight):
self.name = name
self.age = age
self.__weight = weight
def speak(self):
print(f'我叫{self.name},我{self.age}岁,我的体重是{self.__weight}千克',end="")
class Student(People):
def __init__(self,name,age,weight,grade):
People.__init__(self,name,age,weight) # 调用父类构造方法进行初始化
self.grade = grade
def speak(self):
super(Student, student).speak()
print(f',我的分数是:{self.grade}',end="")
student = Student('张三',20,100,50)
student.speak()
print()
class Singer():
def __init__(self,song):
self.song = song
def speak(self):
print(f' 歌曲是:{self.song}')
class Sample(Singer,Student): # 多继承调用父类方法的时候,继承顺序基类在前!!!否则方法调用时会出错
def __init__(self,name,age,weight,grade,song): # 调用父类构造方法进行初始化
Student.__init__(self,name,age,weight,grade)
Singer.__init__(self,song)
sample = Sample('张三',20,100,50,'爸爸')
super(Singer,sample).speak() # 调用Student中的speak方法,查看Sample类继承语句,Student左边的类为Singer
super(Sample,sample).speak() # 调用Singer中的speak方法,查看Sample类继承语句,Singer左边的类为Sample
第六节 重写
- 子类按照自己的需求对继承的方法进行调整,即在子类中重写从父类继承来的方法
# 定义一个表示人的类
class Person(object):
def say_hello(self):
print('打招呼!')
# 定义一个表示中国人的类
class Chinese(Person):
def say_hello(self): # 重写的方法
print('吃了吗?')
chinese = Chinese()
super(Chinese,chinese).say_hello() # 调用父类的方法
chinese.say_hello() # 调用子类重写的方法
@Result
打招呼!
吃了吗?
第七节 多态
- 多态是面向对象的重要特性之一
- 直接表现是让不同类的同一功能可以通过同一接口调用,并表现出不同的行为
class Cat():
def shout(self):
print('喵喵~')
class Dog():
def shout(self):
print('汪汪!')
# 定义一个接口,通过接口调用Cat类和Dog类的shout()方法
def shout(obj):
obj.shout()
cat = Cat()
dog = Dog()
shout(cat)
shout(dog)
@Result
喵喵~
汪汪!
第八节 运算符重载
- 运算符重载后,自定义类也可以进行四则运算
第九章 异常
第一节 异常类型
- 每个异常类对应一个类,程序运行的异常大多继承自Exception类,Exception类又继承自异常类的基类BaseException,它派生了四个子类,KeyboardInterrupt、GeneratorExit、Exception、SystemExit
- NameError:使用未定义的变量引发异常
- IndexError:程序越界访问时发生异常
- AttributeError:使用对象访问不存在的属性引发异常
- FileNotFound:未找到指定文件或目录时引发异常
第二节 异常捕获语句
1.try-except语句捕获异常
try:
可能出错的代码 # 代码出现异常,跳过剩余语句,执行except子句
except [异常类型 [as error]]: # 将捕获到的异常对象赋值给error
捕获异常后的处理代码
- 捕获单个异常
num_one = int(input("请输入被除数:"))
num_two = int(input("请输入除数:"))
try:
print("结果为",num_one/num_two)
except ZeroDivisionError as error:
print("出错了,原因:",error)
@Result
请输入被除数:1
请输入除数:0
出错了,原因: division by zero
- 捕获多个异常,在except后以元组的形式指定多个异常类型
try:
num_one = int(input("请输入被除数:"))
num_two = int(input("请输入除数:"))
print("结果为",num_one/num_two)
except (ZeroDivisionError,ValueError) as error:
print("出错了,原因:",error)
@Result
请输入被除数:1
请输入除数:0
出错了,原因: division by zero
@Result
请输入被除数:1
请输入除数:p
出错了,原因: invalid literal for int() with base 10: 'p'
2.else&finally
- else与finally都可跟在try-except后执行,但二者在用法上由一定区别:
- else后接没有异常的处理代码
- finally后接的代码无论是否有异常一定执行
# else
num_one = int(input("请输入被除数:"))
num_two = int(input("请输入除数:"))
try:
res = num_one/num_two
except (ZeroDivisionError,ValueError) as error:
print("出错了,原因:",error)
else:
print(res)
@Result
请输入被除数:1
请输入除数:2
0.5
# finally
num_one = int(input("请输入被除数:"))
num_two = int(input("请输入除数:"))
try:
res = num_one/num_two
except ZeroDivisionError as error:
print("出错了,原因:",error)
finally:
print("执行finall")
@Result
请输入被除数:1
请输入除数:0
出错了,原因: division by zero
执行finall
第三节 抛出异常
Python中的语句不仅可以自动触发,还可以使用raise语句和assert语句主动抛出
1.使用raise语句抛出异常
- 使用异常类引发异常
# “raise异常类”可以引发该语句中异常类对应的异常,执行时会先隐式地创建该语句中异常类的实例
raise IndexError
@Result
Traceback (most recent call last):
File "D:\Program Files (x86)\Tencent\QQ\test.py", line 1, in <module>
raise IndexError
IndexError # 抛出的异常类实例
- 使用异常类对象引发异常类
# “raise异常类对象”语句可以引发该语句中异常类对象对应的异常
raise IndexError("索引下标超出范围") # 抛出异常及其具体信息
@Result
Traceback (most recent call last):
File "D:\Program Files (x86)\Tencent\QQ\test.py", line 1, in <module>
raise IndexError("索引下标超出范围") # 抛出异常及其具体信息
IndexError: 索引下标超出范围
-
重新引发异常
下例中,try执行后会因raise语句引发的IndexError异常,执行except语句;except子句后的代码又使用raise语句抛出刚刚发生的IndexError异常,最终程序因再次抛出异常而终止执行
# 使用不带任何参数的raise可以引发刚刚发生过的异常
try:
raise IndexError("索引下标超出范围")
except:
raise
@Result
Traceback (most recent call last):
File "D:\Program Files (x86)\Tencent\QQ\test.py", line 2, in <module>
raise IndexError("索引下标超出范围")
IndexError: 索引下标超出范围
2.使用assert语句抛出异常
- assert语句后面紧跟一个表达式,表达式值为Faslse时触发AssertionError异常,值为True时不做任何操作
# 格式
assert 表达式[,异常信息]
- assert语句可以帮助程序开发者在开发阶段调试程序,以保证程序能够正确执行
num_one = int(input("请输入被除数:"))
num_two = int(input("请输入除数:"))
assert num_two != 0,'除数不能为0'
@Result
请输入被除数:4
请输入除数:0
Traceback (most recent call last):
File "D:\Program Files (x86)\Tencent\QQ\test.py", line 3, in <module>
assert num_two != 0,'除数不能为0'
AssertionError: 除数不能为0 # 除数为0时,assert断言值为False,触发异常
3.异常的传递
- 如果程序中的异常没有被处理,默认情况下会将异常传递到上一级,不停传递直至异常被处理或程序崩溃
def get_width():
print("get_width开始执行")
num = int(input("请输入除数:"))
width_len = 10 / num
print("get_width执行结束")
return width_len
def calc_area():
print('calc_area开始执行')
width_len = get_width()
print('calc_area执行结束')
return width_len * width_len
def show_area():
try:
print('show_area开始执行')
area_val = calc_area()
print(f'正方形的面积是:{area_val}')
print('show_area执行结束')
except ZeroDivisionError as e:
print(f'捕捉到异常:{e}')
show_area()
@Result
show_area开始执行
calc_area开始执行
get_width开始执行
请输入除数:0
捕捉到异常:division by zero
show_area()为程序入口,函数中调用了calc_area()函数,calc_area()函数又调用了get_width()函数,当在get_width()函数中输入除数值为0,程序会引发ZeroDivisionError异常,函数内没有异常捕获语句,会向上传递到calc_area()函数,由于没有异常捕获语句,继续向上传递到show_area()函数,在show_area()函数通过try-except处理异常
第四节 自定义异常
在实际开发中可能出现的问题难以预料,有时开发人员需要自定义异常类,以满足当前程序的需要,具体应用实例如下:
import os
'''自定义异常'''
class ImageException(Exception):
def __init__(self,name):
self.name = name
try:
path = "file_write.txt" # 用户上传文件
name = os.path.splitext(path)[-1].lower() # 截取文件拓展名,转为小写
if(name!=".jpg" and name!=".png#pic_center" and name!= ".jpeg"):
raise ImageException(name) # 抛出自定义异常
except ImageException as error:
print("ImageException:文件名为",error.name,",应为JEG、png#pic_center、JPEG")
@Result
ImageException:文件名为 .txt ,应为JEG、png#pic_center、JPEG
# 自定义异常
class NumException(Exception):
def __init__(self,num):
self.num = num
def menu():
print("*************************************")
print("1.西瓜")
print("2.苹果")
print("3.橙子")
print("4.哈密瓜")
while(True):
menu()
try:
cho = int(input("请选择商品:"))
print(cho)
assert 0 < cho < 5,'选择的商品不在范围内' # 断言语句判断选择范围
num = int(input("请输入购买数量:"))
if num < 1:
raise NumException(num) # 抛出自定义异常判断购买数量
except NumException as e:
print("NumException:输入的商品数量应大于1,你输入了:",e.num)
else:
print("购买成功!")