Python
1 变量
1、什么是变量
变量是关联一个对象的标识符
变量可以绑定一个对象,并可以通过变量名使用这个对象
2、变量的命名方法:
以字母或下划线开头,后面跟字母、下划线或者数字
3、python中的关键字不能用作变量名
4、变量无类型,对象有类型
5、在交互模式下查看当前作用域内的所有变量:
help(’main’)
6、自动化内存管理和引用计数
每个对象都会记录有几个变量引用(绑定)自身,当引用的数量为0时,则此对象
2 小整数对象池
Cpython中,整数-5至256永远存在于小整数对象池中,不会释放,可重复使用。
3 赋值语句
- 当变量不存在时,赋值语句会创建该变量,同时将变量绑定在赋值运算符右侧的对象上
- 当变量存在时,改变此变量的绑定关系
- 一个变量只能绑定一个对象
- 多个变量可以同时绑定在一个对象上
4 基本输入输出函数
4.1 基本输入函数
基本输入函数input
- 作用:从一个标准输入设置上读取一个字符串(不包含换行符)
- 格式:input(‘提示字符串‘)
- 说明:返回用户输入的字符串,‘提示字符串‘可以为空
4.2 基本输出函数
基本输入函数print
- 格式:print(value,…,sep=’ ’,end=’\n’,files=sys.stdout,flush=Flase)
- 作用:将一系列的值以字符串形式输出到标准输出设备上
- 参数选项:
- sep: 两个值之间的分隔符(默认为一个空格)
- end: 输出完毕后在末尾自动追加一个字符串(默认为换行符)
- file: 流对象
- flush: 是否立即将流进行输出
5 基本数据类型
python3中常见的数据类型有:Number、String、List、Tuple、Set、Dirctionary。其中,
- 不可变数据:Number、String、Tuple
- 可变数据:List、Set、Dirctionary
5.1 字符串(string)
python中字符串是不可改变的字符序列
5.1.1 索引(index)
- 语法:字符串[表达式]
- 说明:
- python的序列都可以用索引来访问序列中的对象
- python序列的正向索引都是从0开始的,最后一个索引为len(s)-1
- python序列的负向索引是从-1开始的,-1代表最后一个,第一个为-len(s)
5.1.2 切片
- 作用: 从i字符串序列中取出相应的元素重新组成一个新的字符串
- 语法:字符串[(开始索引b):(结束索引e)(:(步长s))]注:小括号()括起来的部分代表可省略
- 说明:
- 开始索引是切片开始切下的位置,0表示第一个元素
- 结束索引是切片的终止索引(但不包含终止点)
- 步长是切片每次获取当前元素后移动的方向和偏移量
- 没有步长,相当于步长为1
- 当步长为正整数时,取正向切片:即开始索引默认为0,结束索引默认是最后一个元素的下一个位置
- 当步长为负整数时,取反向切片:即默认的起始位置为最后一个元素,终止位置为第一个元素的前一个位置
5.1.3 编码转换
ord(c)返回一个字符c的unicode编码值
chr(i)返回i这个值所对应的字符
5.1.4 常用方法
语法:
对象.方法名(方法传参)
5.1.5 格式化表达式
- 作用:生成一定格式的字符串
- 运算符:%
- 格式:
- 格式化字符串 % 参数值
- 格式化字符串 % (参数值1,参数值2,……)
- 说明:格式化字符串中以%开头的字符为占位符,占位符的位置将用参数值替换
- 格式化字符串中的占位符类型码
符号 | 说明 |
---|---|
%s | 字符串,使用str(x) |
%r | 字符串,使用repr(x) |
%c | 整数转为单个字符 |
%d | 十进制整数 |
%o | 八进制整数 |
%x | 十六进制整数(字符a-f小写) |
%X | 十六进制整数(字符A-F大写) |
%e | 指数型浮点数(e小写) |
%E | 指数型浮点数(E大写) |
%f,%F | 浮点十进制数 |
%g,%G | 十进制浮点数或指数浮点自动切换 |
%% | 等同于一个%字符 |
- 占位符和类型码之间的格式语法
- % [ - + 0 宽度.精度 ] 类型码
- -: 左对齐(默认为右对齐)
- +: 显示正号
- 0: 左侧空白位置补零
- 宽度: 整数数据输入的宽度
- 精度: 保留小数点后多少位(默认为6位)
5.1.6 文本解析
- S.split(sep=None):将字符串使用sep作为分隔符分割S字符串,返回分割后的字符串列表;当不给定参数时,用空白字符作为分割符。
- S.join(iterable):用可迭代对象中的字符串生成一个中间用S分隔的字符串。
s = 'Beijing is Captial'
L = s.split(' ') #L = ["Beijing","is","Captial"]
s2 = "##".join(L) #s2 = "Beijing##is##Captial"
5.2 列表(list)
列表是可变的序列,可以通过索引赋值改变列表中的元素
5.2.1 索引
- 语法: x=列表[整数表达式]
- 索引赋值: 列表是可变的序列,可以通过索引赋值改变列表中的元素
- 语法: 列表[整数表达式] = 表达式
5.2.2 切片
-
切片取值
- 语法:列表[起始索引:终止索引:步长]
- 作用:列表的切片取值是从原列表中取出想要的元素再次组成一个新的列表
-
切片赋值
- 作用: 改变原列表的排列,可以插入和修改数据
- 语法: 列表[切片] = 可迭代对象
-
说明: 切片赋值的赋值运算符的右侧必须是一个可迭代对象
注意
对于步长不等于1的切片赋值,赋值运算符的右侧的可迭代对象提供的元素的个数,一定要等于切片切出的段数
5.2.3 python3 中常用于序列的函数
函数 | 描述 |
---|---|
len(x) | 返回序列的长度 |
max(x) | 返回序列中的最大值元素 |
min(x) | 返回序列中的最小值元素 |
sum(x) | 返回序列中所有元素的和(元素必须是数字类型) |
any(x) | 真值测试,如果列表中的一个值为真值,则返回True |
all(x) | 真值测试,如果列表中所有的值为真值,则返回True |
5.2.4 常用的列表方法
5.2.5 列表推导式
- 描述:用可迭代对象创建列表的表达式
- 作用: 创建列表
- 语法: [表达式 for 变量 in 可迭代对象]
或
[表达式 for 变量 in 可迭代对象 if 真值表达式]
#生成一个数值1-9的平方的列表(只要其中奇数的平方)
L = [x**2 for x in range(1,10) if x % 2 == 1]
- 列表推导式的嵌套语法:
[表达式
for 变量1 in 可迭代对象1 if 真值表达式1
for 变量2 in 可迭代对象2 if 真值表达式2
...
]
5.3 元组(tuple)
元组时不可变的序列,元组是可以存储任意类型的数据的容器
- 语法: 用小括号括起来,单个元素括起来后加逗号来区分单个对象还是元素
- 常用方法:
5.4 字典(Dictionary)
5.4.1 定义
- 字典是一种可变的容器,可以存储任意类型的数据
- 字典中的每个数据都是用键进行索引,而不像序列可以用整数进行索引
- 字典中的数据没有先后顺序关系,它的存储是无序的
- 字典中的数据以键值对形式进行存储
- 字典中的键不能重复,且只能用不可变类型作为字典的键
5.4.2 字典的键索引
- 语法:字典[键]
- 作用:用键获取字典的键所对应的值
d = {'name': 'tarena', 'age': 16}
print(d['name'], "的年龄是", d['age'])
5.4.3 添加和修改字典的元素
- 语法:字典[键] = 值
- 说明:键不存在时,创建键并让键绑定对应的值;键存在则修改键绑定的值
5.4.4 字典的迭代访问
字典是可迭代队形,字典只能对键进行迭代访问
5.4.5 字典推导式
- 说明:字典推导式是用可迭代对象来创建字典的表达式
- 语法:
{键表达式:值表达式 for 变量 in 可迭代对象
[if 真值表达式]}
#生成一个字典:键为数字0-9,值为键的平方
d = {x:x**2 for x in range(1,10)}
5.4.6 常用方法
5.5 集合
5.5.1 定义
- 集合是可变的无序的容器
- 集合内的数据都是唯一的(不可重复)
- 集合中的数据没有先后顺序
- 集合内的元素必须是不可变对象
- 集合是可迭代的
- 集合是相当于只有键没有值的字典
5.5.2 运算
&:生成两个集合的交集
s1 = {1,2,3}
s2 = {2,3,4}
s3 = s1 & s2 #s3 = {2,3}
|:生成两个集合的并集
s1 = {1,2,3}
s2 = {2,3,4}
s3 = s1 | s2 #s3 = {1,2,3,4}
-:生成两个集合的补集(即生成属于s1但不属于s2的所有元素的集合)
s1 = {1,2,3}
s2 = {2,3,4}
s3 = s1 - s2 #s3 = {1}
^:生成两个集合的对称补集
s1 = {1,2,3}
s2 = {2,3,4}
s3 = s1 ^ s2 #s3 = {1,4}
<:判断一个集合是另一个集合的子集
>:判断一个集合是另一个集合的超集
5.5.3 常用方法
5.6 数据类型转换
以下几个内置的函数可以执行数据类型之间的转换。这些函数返回一个新的对象,表示转换的值。
函数 | 描述 |
---|---|
int(x) | 将x转换为一个整数 |
float(x) | 将x转换为一个浮点数 |
complex(real[,imag]) | 创建一个复数 |
str(x) | 将x转换为字符串 |
repr(x) | 将x转换为表达式字符串 |
eval(str) | 用于计算在字符串中的有效python表达式,并返回一个对象 |
tuple(s) | 将序列s转换为一个元组 |
list(s) | 将序列s转换为一个列表 |
set(s) | 将序列s转换为一个集合 |
frozenset(s) | 将序列s转换为一个固定集合 |
dict(d) | 创建一个字典。d必须是一个(key,value)元组序列 |
chr(x) | 将一个整数转换为一个字符 |
ord(x) | 将一个字符转换为它的整数值 |
hex(x) | 将一个整数转换为一个十六进制字符串 |
oct(x) | 将一个整数转换为一个八进制字符串 |
6 python运算符优先级
7 深拷贝和浅拷贝
- 浅拷贝:即在复制过程中,只复制一层变量,不会复制深层变量绑定的对象的复制过程。
L = [3.1, 3.2]
L1 = [1, 2, L]
L2 = L1.copy() # 浅拷贝
print(L1) # [1, 2, [3.1, 3.2]]
print(L2) # [1, 2, [3.1, 3.2]]
L2[2][0] = 3.14
print(L1) # [1, 2, [3.14, 3.2]]
print(L2) # [1, 2, [3.14, 3.2]]
- 深拷贝:完全拷贝,内嵌变量的修改不会影响另外一个变量
import copy # 导入复制模块
L = [3.1, 3.2]
L1 = [1, 2, L]
L2 = copy.deepcopy(L1) # 深拷贝
print(L1) # [1, 2, [3.1, 3.2]]
print(L2) # [1, 2, [3.1, 3.2]]
L2[2][0] = 3.14
print(L1) # [1, 2, [3.1, 3.2]]
print(L2) # [1, 2, [3.14, 3.2]]
8 if语句
- 作用:让程序根据条件选择性的执行某条语句或者某些语句
- 语法:
if 真值表达式1:
语句块1
elif 真值表达式2:
语句块2
...
else:
语句块3
- 说明:
- elif子句可以有0个、1个或多个
- else子句可以有0个或1个,且只能放在if语句的最后面
- if语句嵌套:
- if语句本身是由多条子句组成的一条复合语句
- if语句可以作为语句嵌套在另一个复合语句的内部
- 条件表达式:
- 作用:根据真值表达式的取值来决定执行表达式1或者表达式2,并返回结果。
- 语法:
表达式1 if 真值表达式 else 表达式2
9 while语句
- 作用:根据一定条件,重复执行一条或多条语句
- 语法:
while 真值表达式:
语句块1
else:
语句块2
- 说明:
- 1、先执行真值表达式,得到布尔值为True或False
- 2、如果针织表达式的值为真,则执行语句块1,然后再返回第一步,重复执行测试真值表达式的值;如果真值表达式的值为假,则执行else子句部分的语句块2,然后结束此while语句的执行。
- else子句部分可以省略
- 注意事项:
- 要控制循环的真值表达式的值来防止死循环
- 通常用真值表达式内的循环变量来控制循环条件
- 通常在语句内部改变循环变量
10 for语句
- 作用:用来遍历可迭代对象的数据元素(可迭代对象即能依次获取数据元素的对象)
- 语法:
for 变量列表 in 可迭代对象:
语句块1
else:
语句块2
- 说明:
- 当在循环体内使用break终止循环时,else子句部分的语句不会执行
- else子句部分可以省略
- for语句嵌套
for x in "abc":
for y in "123":
print(x+y) #a1,a2,a3,...,c3
11 break语句
- 作用:用于循环语句中,终止当前循环语句的执行
- 说明:
- 当break语句执行后,此循环语句break之后的语句将不再执行
- break语句通常与if语句组合使用
- break语句终止循环时,循环语句的else子句的语句不会执行
- break语句只能终止当前循环语句的执行,如果有循环嵌套时,不会跳出嵌套的外层循环
- break语句只能在循环语句的内部使用
#使用break语句来终止循环
i = 1
while i < 6:
print("===循环开始时i的值为%s===" % str(i))
if i == 3:
break
i += 1
else:
print("while中的else子句被执行")
print("程序结束")
输出结果为:
===循环开始时i=1===
===循环开始时i=2===
===循环开始时i=3===
程序结束
- 死循环
- 死循环,即循环条件一直成立的循环
- 死循环通常能用break语句来终止循环
- 死循环的else子句永远不会执行
12 continue语句
- 作用:用于循环语句中,不再执行本次循环内continue之后的语句,重新开始一次新的循环
- 说明:
- 在while语句中执行continue语句,将会直接跳到while语句的真值表达式处,重新判断循环条件
- 在for语句中执行continue语句,将会从可迭代对象中取下一个数据绑定变量后再次进行循环
13 函数
- 定义:函数是可以重复执行的语句块,可以重复调用并执行。函数是面向过程编程的最小单位。
- 作用:
- 用于封装语句块,提高代码的重用性;
- 定义用户级别的函数
- 提高代码的可读性和易维护性
13.1 def语句
- 语法
def 函数名(形参列表):
语句块
- 作用:创建一个函数,将语句块打包,用函数名绑定,用来调用
- 说明:
- 函数名的命名规则和变量名的规则相同
- 函数名是一个变量,它用来绑定函数
- 函数有自己的名字空间,在函数外部不可以访问函数内部的变量,在函数内部可以访问函数外部的变量,但不能对外部的变量赋值
- 语句块部分不能为空,如果为空需要填充pass语句
- 函数如果不需要传入参数,形参列表可以为空
- 函数调用:
- 说明:函数调用是一个表达式,如果函数内部没有return语句,函数执行完毕后返回None。
- 语法
函数名(实际调用传递参数)
13.2 return语句
- 语法:
return [表达式] #注:[]表示其中的内容可省略
- 作用:用于函数中,结束当前函数的执行,返回到调用该函数的位置,同时返回一个对象的引用关系
- 说明:
- return语句后面的表达式可以省略,省略后相当于return None
- 函数内部没有return语句,则函数执行完最后一条语句后返回None
13.3 函数的参数传递
13.3.1 传递方式
- 传递方式:
- 位置传参
- 序列传参
- 关键字传参
- 字典关键字传参
- 位置传参
13.3.2 位置传参
实际参数(实参)的对应关系与形式参数(形参)的对应关系是按位置来依次对应的
- 说明:
- 实参和形参通过位置来传递和匹配;
- 实参的个数必须和形参的个数相同
- 序列传参:在函数调用过程中,用(*)将序列拆解后按位置进行传递的传参方式。
- 说明:
- 序列传参时,序列拆解的位置将于形参一一对应。
- 说明:
13.3.3 关键字传参
关键字传参即传参时,按照实参名称给形参赋值,实参和形参按名称进行匹配。
- 说明:可以不按照位置进行匹配
- 字典关键字传参:即实参为字典,将字典用**拆解后进行关键字传参的传递方式。
- 说明:
- 字典的键名和形参名必须一致;
- 字典的键名必须为符合标识符命名规则的字符串
- 字典的键名要在形参中体现
- 说明:
13.3.4 函数的综合传参
- 函数的传参方式在能确定形参能唯一匹配到的相应实参的情况
- 函数的位置传参要优于关键字传参
13.4 函数的缺省参数
- 语法:
def 函数名(形参名1=默认实参1,形参名2=默认实参2,...)
- 作用:让函数的调用者少传递参数来调用函数
- 说明:
- 缺省参数必须从右到左依次存在,如果一个参数有缺省参数,则其右侧的所有参数都必须有缺省参数
- 缺省参数可以有0个、1个或多个,甚至全部都是缺省参数
13.5 函数的可变实参和不可变实参的传递
python函数的参数传递:
- 传不可变对象实例:类似C++的值传递,如整数、字符串和元组。如func(a),传递的只是a的值,没有影响a对象本身。如果在func(a)内部修改a的值,则是新生成一个a的对象。
#通过id()函数来查看内存地址的变化
def change(a):
print(id(a))
a = 10
print(id(a))
a = 1
print(id(a))
change(a)
输出结果为:
1698999763184
1698999763184
1698999763472
可以看到在调用函数前后,形参和实参指向的是同一个对象(对象id相同),在函数内部修改形参后,形参指向的是不同的id。
- 传可变对象实例:类似C++的引用传递,如列表、字典。如func(la),则是将la真正的传过去,修改后func外部的la也会受影响。
#可变对象在函数里修改了参数,那么在调用这个函数的函数里,原始的参数也被改变了
def changeme(mylist):
mylist.append([1,2,3])
print("函数内取值:", mylist)
return
mylist = [10,20,30]
changeme(mylist)
print("函数外取值:",mylist)
输出结果为:
函数内取值: [10, 20, 30, [1, 2, 3]]
函数外取值: [10, 20, 30, [1, 2, 3]]
13.6 函数形参的定义方式
13.6.1 位置形参
- 语法
def 函数名(形参变量1,形参变量1,...)
语句块
13.6.2 星号元组形参
- 语法:
def 函数名(*元组形参名)
语句块
- 作用:收集多余的位置传参
- 说明:元组形参名一般为args;元组形参一个函数只能有一个
def func(*args):
print("形参的个数是:", len(args))
print("args=", args)
print("\n")
func()
func(1,2,3)
func(1,2,3,4,5,6,7,8)
s = "abcdef"
func(s)
func(a=100,b=200)
输出结果为:
形参的个数是: 0
args= ()
形参的个数是: 3
args= (1, 2, 3)
形参的个数是: 8
args= (1, 2, 3, 4, 5, 6, 7, 8)
形参的个数是: 1
args= ('abcdef',)
Traceback (most recent call last):
File "D:\Code\python\test.py", line 10, in <module>
func(a=100,b=200)
TypeError: func() got an unexpected keyword argument 'a'
13.6.3 命名关键字形参
- 语法:
def 函数名(*/*args,命名关键字形参1,命名关键字形参1,...)
语句块
- 作用:强制所有的命名关键字形参都必须用关键字传参或字典关键字传参
def func(a,b,*,c,d):
print(a,b,c,d)
print("\n")
#func(1,2,3,4) #传参失败
func(1,2,c=30,d=40)
func(a=10,b=20,c=30,d=40)
func(1,2,**{"c":300,"d":400})
输出结果为:
1 2 30 40
10 20 30 40
1 2 300 400
13.6.4 双星号字典形参
- 语法
def 函数名(**字典形参名)
语句块
- 作用:收集多余的关键字传参
- 说明:
- 字典形参名一般命名为:kwargs
- 一个函数内字典形参最多一个
def func(**kwargs):
print("关键字传参的个数是:",len(kwargs))
print("kwargs=",kwargs)
print("\n")
func(name="Torres",age=18,address="wuhan")
def func1(*,a,b,**kwargs):
print("关键字传参的个数是:",len(kwargs))
print("kwargs=",kwargs)
print("\n")
func1(a=1,b=2,c=3,d=4)
输出结果为:
关键字传参的个数是: 3
kwargs= {'name': 'Torres', 'age': 18, 'address': 'wuhan'}
关键字传参的个数是: 2
kwargs= {'c': 3, 'd': 4}
13.6.5 形参说明
- 位置形参、缺省参数、星号元组形参、双星号字典形参可以混合使用
- 函数形参从左到右的定义顺序为:位置形参、星号元组形参、命名关键字形参、双星号字典形参
def func(a,b,*args,**kwargs):
print("args=",args)
print("kwargs=",kwargs)
func(1,2,3,4,c=30,d=40,e=50)
输出结果为:
args= (3, 4)
kwargs= {'c': 30, 'd': 40, 'e': 50}
13.7 全局变量和局部变量
13.7.1 全局变量
- 定义在函数外部,模块内部的变量称为全局变量
- 全局变量所有的函数都可以直接访问(但函数内部不能对其直接赋值)
Tips:
函数内部的赋值语句不会对全局变量造成影响
13.7.2 局部变量
- 定义在函数内部的变量为局部变量(函数形参也是局部变量)
- 局部变量只能在函数内部使用
- 局部变量在函数调用时才能创建,在函数调用之后会自动销毁
13.8 globals函数和locals()函数
- globals():返回当前全局作用域内变量的字典
- locals():返回当前局部作用域内变量的字典
a = 1
b = 2
c = 3
def fn(c, d):
e = 300
print("local()返回:", locals())
print("global()返回:", globals())
print(a, b, c, d, e) # 1, 2, 100, 200, 300
x = globals()
print("全局变量c的值是:", x['c'])
fn(100, 200)
输出结果为:
local()返回: {'c': 100, 'd': 200, 'e': 300}
global()返回: {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000001A84FCC7C40>, '__spec__': None, '__annotations__': {}, '__builtins__':
<module 'builtins' (built-in)>, '__file__': 'D:\\Code\\python\\test.py', '__cached__': None, 'a': 1, 'b': 2, 'c': 3, 'fn': <function fn at 0x000001A84FD23E20>}
1 2 100 200 300
全局变量c的值是: 3
13.9 函数变量
- 函数名是变量,它在创建函数时绑定一个函数
def func1():
print("func1函数被调用")
func2 = func1 #看清楚,不是func2 = func1()
func2()
func1()
输出结果为:
func1函数被调用
func1函数被调用
- 一个函数可以作为另一个函数的实参传递,可以将一个函数给另一个函数,另一个函数的形参变量将绑定实参函数,同时函数也可以作为另一个函数的返回值。
def func1():
print("func1函数被调用")
def func2():
print("func2函数被调用")
def get_func(n):
if n == 1:
return func1
elif n == 2:
return func2
funcx = get_func(1)
funcx() #调用func1
funcx = get_func(2)
funcx() #调用func2
输出结果为:
func1函数被调用
func2函数被调用
13.10 python中的四个作用域LEGB
- Local:局部作用域
- Enclosing Function local:外部嵌套函数作用域
- Global:函数定义所在模块的作用域
- Builtin:python内建模块的作用域
注意:
变量名的查找规则:L --> E -->G -->B
在默认情况下,变量名赋值会创建或改变当前作用域内变量的绑定关系
v = 100
def func1():
v = 200
print("func1.v=",v)
def func2():
v = 300
print("func2.v", v)
func2()
func1()
print("v=",v)
输出结果为:
func1.v= 200
func2.v 300
v= 100
13.11 global语句
- 作用:
- 告诉解释执行器,global语句声明的一个或多个变量,这些变量的作用域为模块级的作用域,亦称全局变量
- 全局声明将赋值语句的变量映射到模块文件内部的作用域
- 语法
global 变量名1,变量名2……
- 说明
- 全局变量如果要在函数内部被赋值,则必须经过全局声明,否则会被认为是局部变量
- 全局变量在函数内部不经过声明即可直接访问
- 不能先创建局部变量,再用global声明为全局变量,此种做法不符合规则
- global变量列表里的变量名不能出现在函数的形参列表里
v = 100
def func():
#global声明v为全局变量
global v
v = 200
func()
print("v=",v)
输出结果为:
v= 200
13.12 nonlocal语句
-
作用:告诉解释执行器,nonlocal声明的变量不是局部变量,也不是全局变量,而是外部嵌套函数内的变量
-
语法:
nonlocal 变量名1,变量名2……
- 说明:
- nonlocal 语句只能在被嵌套函数内部进行使用
- 对nonlocal变量进行赋值将对外部嵌套函数作用域内的变量进行操作
- 当有两层或两层以上函数嵌套时,访问nonlocal变量只对最近的一层变量进行操作
- nonlocal语句的变量列表里的变量名不能出现在此函数的形参列表里
v = 100
def func1():
v = 200
print("func1.v",v)
def func2():
nonlocal v
v = 300
print("func2.v",v)
func2()
print("func1.v",v)
func1()
print("全局v=",v)
输出结果为:
func1.v 200
func2.v 300
func1.v 300
全局v= 100
13.13 lambda表达式(匿名函数)
- 作用:创建一个匿名函数对象,同def类似,但不提供函数名
- 语法
lambda [函数形参列表]: 表达式
- 说明:
- lambda表达式创建的函数只能包含一条表达式
- lambda比函数简单,且可以随时创建和销毁,有利于降低程序的耦合度
###
#def myadd(x,y):
# return x+y
#print("4+5=",myadd(4,5))
print("4+5=",(lambda x,y: x+y)(4,5))
输出结果为:
4+5= 9
13.14 eval函数和exec函数
- eval(source,global=None,local=None):把一个字符串source当成一个表达式来执行,返回表达式执行后的结果。
str1 = "1 + 2 * 3 + 4"
v = eval(str1)
print(v)
while True:
str = input(">>> ")
print(eval(str))
输出结果:
11
>>> 1+2+3
6
- exec(source, global=None, local=None):把一个字符串source当成程序来执行
str1 = '''
myadd = lambda x,y: x+y
print("20 + 30=",myadd(20,30))
print("3 + 7=", myadd(3,7))
'''
exec(str1)
输出结果为:
20 + 30= 50
3 + 7= 10
13.15 函数式编程
函数式编程是指:用一系列函数解决问题。函数是一等公民
- 优点:
- 用每个函数完成细小的功能,一系列函数的任意组合可以解决发问题
- 函数仅接受输入并产生输出,不包含任何能影响输出的内部状态
13.16 函数的可重入性
- 定义:当一个函数的输入实参一定,输出结果也一定的函数称为可重入函数。
- 说明:可重入函数在函数内部一定不访问除局部变量以外的变量。
#可重入函数
def myadd(x,y):
return x + y
#不可重入函数
s = 0
def myadd2(x,y):
global s
s += x + y
return s
14 高阶函数
满足下列条件中的一个的函数即为高阶函数:
- 函数接受一个或多个函数作为参数传入
- 函数返回一个函数
14.1 map函数
map(func, *iterable):返回一个可迭代对象,此迭代对象用函数func对可迭代对象iterable中的每一个元素作为参数计算后得到一个结果,当最短的一个可迭代对象不再提供数据时,可迭代对象生成数据结束。
def pow2(x):
return x ** 2
for x in map(pow2,range(1,10)):
print(x)
输出结果为
1
4
9
16
25
36
49
64
81
14.2 filter函数
filter(func, iterable):返回一个可迭代对象,此迭代对象将对iterable获取到的数据用函数function进行筛选。function将对iterable中的每个元素进行求值,返回False则将此数据丢弃;返回True,则保留此数据。
def myadd(x):
return x % 2 == 1
for x in filter(myadd,range(11)):
print(x)
输出结果为:
1
3
5
7
9
14.3 sorted函数
- 描述:sorted()函数对所有可迭代的对象进行排序操作
- 语法:
sorted(iterable,key=None,reverse=False)
- 参数说明
- iterable:可迭代对象
- key:主要是用来进行比较的元素,只有一个参数,具体的函数的参数就是取自于可迭代对象中,指定可迭代对象中的一个元素来进行排序。
- reverse:排序规则,reverse=True降序,reverse=False升序(默认)
- 返回值:返回重新排序后的列表
sort和sorted的区别:
- sort是应用在列表list上的方法,sorted可以对所有可迭代对象进行排序操作
- list的sort方法返回的是对已经存在的列表进行操作,无返回值;而内建函数sorted方法返回的是一个新的list,而不是在原来的基础上进行的操作。
以下实例对sorted函数进行展示:
a = [5,7,6,3,4,1,2]
b = sorted(a)
print("a",a)
print("b",b)
L=[("b",2),("a",1),("c",3),("d",4)]
#利用key函数
key_L = sorted(L,key=lambda x:x[1])
print("key_L",key_L)
#利用reverse
rev_L = sorted(L,key=lambda x:x[1],reverse=True)
print("rev_L",rev_L)
输出结果为:
a [5, 7, 6, 3, 4, 1, 2]
b [1, 2, 3, 4, 5, 6, 7]
key_L [('a', 1), ('b', 2), ('c', 3), ('d', 4)]
rev_L [('d', 4), ('c', 3), ('b', 2), ('a', 1)]
15 递归函数
递归函数,即直接或间接的调用自身。
def func():
func()
func()
- 说明:递归函数一定要控制递归的层数,当符合某一条件时要终止递归调用。几乎所有的递归都可以用while循环来代替。
- 优点:递归可以把问题简单化,让思路更为清晰,代码更简洁
- 缺点:递归受系统环境影响大,当递归深度太大时,可能会得到不可预知的结果。
- 递归函数的执行分为两个阶段:
- 递推阶段:调用进入函数内部
- 回归阶段:返回结果,得到最终结果
def fx(n):
print("递归进入第%d层" % n)
if n == 3:
return
fx(n+1)
print("递归退出第%d层" % n)
fx(1)
print("程序结束")
输出结果为:
递归进入第1层
递归进入第2层
递归进入第3层
递归退出第2层
递归退出第1层
程序结束
16 闭包
闭包是指引用了此函数外部变量的函数(外部变量指的是:外部嵌套函数作用域内的变量)。闭包必须满足三个条件:
- 必须有一个内嵌函数
- 内嵌函数必须引用外部函数的变量
- 外部函数的返回值必须是内嵌函数
注意:由于闭包会使得函数中的变量都被保存在内存中,内存消耗比较大,所以不能滥用闭包。
def make_power(y):
def fn(x):
return x ** y
return fn
pow2 = make_power(2)
print("5的平方是:",pow2(5))
#========================================
def get_funs(n):
L = []
for i in range(n):
L.append(lambda x:x * i)
return L
funs = get_funs(4)
print(funs[0](10))
print(funs[1](10))
print(funs[2](10))
print(funs[3](10))
#此函数主要看最后i的值是多少
17 装饰器
装饰器是Python中的一种高级功能,它允许你动态地修改函数或类的行为。
装饰器是一种函数,它接受一个函数作为参数,并返回一个新的函数或修改原来的函数。
装饰器的语法使用@decorator_name
来应用在函数或方法上。
Python还提供了一些内置的装饰器,比如@staticmethod
和@classmethod
,用于定义静态方法和类方法。
17.1 装饰器的应用场景
- 日志记录:装饰器可用于记录函数的调用信息、参数和返回值
- 性能分析:可以使用装饰器来测量函数的执行时间
- 权限控制:装饰器可用于限制对某些函数的访问权限
- 缓存:装饰器可用于实现函数结果的缓存,以提高性能
17.2 基本语法
Python装饰器允许在不修改原有函数代码的基础上,动态地增加或修改函数的功能,装饰器本质上是一个接收函数作为输入并返回一个新的包装过后的函数的对象。
def mydeco(fn):
def fx():
print("+" * 13)
fn()
print("-" * 13)
return fx
@mydeco #等同于 myfunc = mydeco(myfunc)
def myfunc():
"""此函数将作为被装饰函数"""
print("myfunc函数被调用")
myfunc()
运行结果为:
+++++++++++++
myfunc函数被调用
-------------
18 模块
- 定义:模块是一个包含所有你定义的函数和变量的文件,其后缀名是.py。模块可以被别的程序引入,以使用该模块中的函数等功能,这也是使用python标准库的方法。
- 作用:
- 让一些相关的数据、函数、类等有逻辑的组织在一起,使逻辑更加清晰
- 模块中的数据、函数和类等可提供给其他模块或程序使用
18.1 模块的分类
- 内置模块:在解析器的内部可以直接调用
- 标准库模块:安装python时已安装,可直接调用
- 第三方模块:需要自己安装(pip install 模块名)
- 自定义模块:用户自己编写的模块
18.2 模块的导入
-
import语句
- 语法:import 模块名1 (as 模块新名1),模块名2 (as 模块新名2)……
- 作用:将某模块整体导入到当前模块
- 用法:模块名.属性名(math.pi)
-
from import 语句
- 语法:from 模块名 import 模块属性名1 (as 属性新名1)……
- 作用:将某模块内的一个或多个属性导入到当前模块的作用域
from math import sin,cos,tan
- from 模块名 import *
- 作用:将某模块的所有属性导入到当前模块
18.3 dir()函数
内置的dir()函数可以找到模块内定义的所有名称。以一个字符串列表的形式返回
- 说明:
- 若没有参数调用,则返回当前作用域内所有变量的列表;
- 若给定一个对象作为参数,则返回这个对象所有变量的列表。
对于一个模块,返回这个模块的全部变量(属性);对于一个类对象,返回类对象的所有变量,并递归基类对象的所有变量;对于其他对象,返回所有变量、类变量和基类变量
18.4 自定义模块并导入
-
要求:
- 模块文件名后缀名必须以.py结尾;
- 模块文件名必须时合法的标识符;
- 避免名称和内建模块名冲突
-
导入方式:
import 语句、from import 语句、from import * 语句
-
import语句查找模块文件的路径顺序
- 搜索内建模块
- 搜索程序运行时的路径
- sys.path提供的路径
-
模块化编程优点:
- 有利于多人合作开发;
- 使代码更加易于维护;
- 提高代码的复用率;
- 有利于解决变量名冲突问题(模块内的全局变量的作用域为模块内全局)
注:模块内的全局变量被称作属性
-
模块的加载过程:在模块导入时,模块内的所有语句都会执行。如果一个模块已经导入,则再次导入时不会重新执行模块内的语句
-
模块被导入和执行的过程
- 先搜索相关路径找到模块名.py
- 判断是否有此模块对应的pyc文件,如果.pyc文件比.py文件新则直接加载.pyc文件;如果.pyc文件比.py文件旧,则用模块名.py生成.pyc文件并加载执行
-
模块的编译
模块名.py -------->模块名.pyc---------->python3
编译 解释执行
-
模块的属性
-
_doc__属性:用于绑定模块的文档字符串_
-
_file__属性:用于绑定模块的文件路径名
-
__name__属性:用于记录模块自身的名字
- 作用:1、记录文件名;2、用于判断是否为主模块
- 说明:
- 当模块作为主模块运行时,__name__绑定”main”,当不是主模块时,__name__属性绑定模块名
-
隐藏属性:模块中以”_”开头的属性,在用from xxx import *导入时将不被导入,这些属性通常被称为隐藏属性
-
19 包
包是将模块以文件夹的组织形式进行分组管理的方法
- 作用:将一系列模块进行分类管理,有利于防止命名冲突,可以在需要时加载一个或部分模块,而不是全部模块
19.1 包的导入
同模块的导入规则
import 包名 [as 包别名]
import 包名.模块名 [as 模块新名]
import 包名.子包名.模块名 [as 模块新名]
from 包名 import 模块名 [as 模块新名]
from 包名.子包名 import 模块名 [as 模块新名]
from 包名.子包名.模块名 import 属性名 [as 属性新名]
from 包名 import *
from 包名.模块名 import *
……
19.2 init.py文件
它是常规包内必须存在的文件;它会在包加载时被自动调用
-
作用:用于记录此包中有哪些包或模块需要导入,当用from 包 import *语句导入模块时,只查找__all__中所有的模块或子包
-
说明: __all__列表只在from xxx import *语句中起作用
20 异常
何为错误?
错误是指由于逻辑或语法等导致程序无法正常执行的问题。其特点:无法预知
何为异常?
异常是程序出错时标识的一种状态,当异常发生时,程序不会再向下执行,而转去调用此函数的地方待处理此错误并恢复为正常状态。其作用:作为信号通知,通知上层调用者有错误产生需要处理
20.1 try-except语句
- 语法:
try:
可能触发异常的语句
except 错误类型1 [as 变量1]:
异常处理语句1
except (错误类型2,错误类型3) [as 变量2]:
异常处理语句2
……
except:
异常处理语句other
else:
未发生异常的语句
finally:
最终语句
- 作用:尝试捕获错误,得到异常通知,将程序由异常状态转换为正常状态并继续执行
- 说明:
- as 子句用于绑定错误对象的变量,可以省略
- except子句可以有一个或多个,但至少要有一个
- else子句最多只能有一个,可以省略
- finally子句最多只能有一个,亦可省略
20.2 try-finally语句
- 语法:
try:
可能触发异常的语句
finally:
最终语句
- 说明:finally子句不可以省略;一定不存在except子句
- 作用:通常用try-finally语句来做触发异常时必须要处理的事情;无论异常发生与否,finally子句都会被执行
注:try-finally语句不会改变程序的状态
def fry_egg():
print("打开天燃气...")
try:
count = int(input("请输入鸡蛋个数:"))
print("完成煎鸡蛋,共煎了%d个鸡蛋!" % count)
finally:
print("关闭天燃气!")
try:
fry_egg()
except ValueError as err:
print("发生值错误,已处理并转为正常状态")
print("程序正常结束")
输出结果为:
打开天燃气...
请输入鸡蛋个数:3
完成煎鸡蛋,共煎了3个鸡蛋!
关闭天燃气!
程序正常结束
20.3 python3中全部的错误类型
20.4 raise语句
- 作用:触发一个错误,让程序进入异常状态,发送错误通知给调用者
- 语法:
raise 异常类型
或
raise 异常对象
或
raise #重新触发上一次异常
20.5 assert语句(断言语句)
- 语法:
assert 真值表达式,错误数据(通常为字符串)
- 作用:当真值表达式为False时,用错误数据创建一个AeesrtionError类型的错误,并进入异常状态,通常用来故意制造一个错误。等同于
if bool(真值表达式)== False:
raise AssertionError
小结
- try-except:用于捕获错误通知,把异常状态转为正常状态
- try-finally:用于执行再任何状态都必须要执行的语句
- raise:触发错误(发送错误通知),让程序进入异常状态
- assert:根据条件触发AssertionError类型的错误通知
21 迭代器
迭代器是可以访问可迭代对象的工具
迭代器是指iter(obj)函数返回的对象(实例)
迭代器可以用next(it)函数获取可迭代对象的数据
21.1 迭代器函数iter和next
- iter(iterable):从可迭代对象中获取一个迭代器,iterable必须是能提供一个迭代器的可迭代对象
- next(Iterator):从迭代器iterator中获取下一个记录,如果无法获取下一个记录,则触发StopIteration异常
说明:
迭代器只能往前取值,不会后退;
用iter函数可以返回一个可迭代对象的迭代器
L = [2,3,5,7]
it = iter(L)
print(next(it))
print(next(it))
print(next(it))
print(next(it))
print(next(it))
输出结果为:
2
3
5
7
Traceback (most recent call last):
File "E:\Code\Python\test01.py", line 8, in <module>
print(next(it))
StopIteration
21.2 迭代工具函数
-
作用:生成一个符合条件的可迭代对象
-
zip(iter1 [,iter2,...]):返回一个zip生成器对象,此对象用于生成一个元组,此元组的数据分别来自于参数中的每个可迭代对象,生成的元素的个数由最小的一个可迭代对象决定
-
enumerate(iterable,start=0):返回一个enumerate生成器对象,此对象生成类型为(索引、值)的元组,默认索引从0开始,也可以用start指定索引位置。
21.3 迭代器协议
迭代器协议是指对象能够使用next函数获取下一项数据,在没有下一项数据时触发一个StopIteration异常来终止迭代的约定。
迭代器协议的实现方法 : next(self) 方法来实现迭代器协议
21.4 什么是可迭代对象:
可迭代对象是指能用iter(obj) 函数返回迭代器的对象(实例);可迭代对象的内部要定义 iter(self) 方法来返回迭代器对象(实例)。
22 生成器
生成器是能够动态提供数据的可迭代对象;
生成器在程序运行时生成数据,与容器类不同,它通常不会在内存中保存大量的数据,而是现用现生成。
22.1 生成器函数
-
定义:含有yield语句的函数是生成器函数,此函数被调用将返回一个生成器对象
-
说明:
- 生成器函数的调用将返回一个生成器对象,生成器对象是一个可迭代对象
- 生成器函数用return会触发一个StopIteration异常
def myinteger(n):
i = 0
while i < n:
yield i
i += 1
for x in myinteger(3):
print(x)
L = [x for x in myinteger(10)]
print(L)
输出结果为
0
1
2
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
22.2 yield语句
- 语法:
yield 表达式
- 说明:
- yield只能用于def函数中,目的是将此函数作为生成器函数使用;
- yield用来生成数据,供迭代器的next()函数使用
def myyield():
print("即将生成2")
yield 2
print("即将生成3")
yield 3
print("即将生成5")
yield 5
print("即将生成7")
yield 7
print("生成结束")
r = myyield()
#拿到生成器的迭代器
it = iter(r)
print(next(it))
print(next(it))
print(next(it))
print(next(it))
print(next(it))
输出结果为:
即将生成2
2
即将生成3
3
即将生成5
5
即将生成7
7
生成结束
Traceback (most recent call last):
File "E:\Code\Python\test01.py", line 19, in <module>
print(next(it))
StopIteration
23 文件
文件是用于存储数据的基本单位,文件通常用来长期存储数据,文件中数据是以字节为单位进行顺序存储的。
- 文件的操作流程:打开文件、读/写文件、关闭文件
注:任何操作系统,一个应用程序同时打开文件的数量由最大数限制
- 文件的打开函数
open(filename,mode=‘rt’):用于打开一个文件,返回用来操作此文件的文件流对象,如果打开失败,则会触发OSError错误通知
- 文件流对象的关闭方法
F.close():关闭文件,释放系统资源
try:
# 1. 打开文件
# myf = open('myfile.txt') # 相对路径
filename = '/home/tarena/aid1809/pbase/day16/code/myfile.txt' #没有这个文件
myf = open(filename) # 绝对路径
print("文件打开成功")
# 2. 读/写文件
# 3. 关闭文件
myf.close()
print("文件已经关闭")
except OSError:
print("文件打开失败")
输出结果为:
文件打开失败
23.1 文本文件的读写操作
23.2 python文件常用方法
23.3 python的文本文件模式
-
模式:t
-
说明:
- 对文本文件的读写操作需要用字符串(str)进行读写操作
- 在读写过程中会自动进行编码和解码操作
- 以行为单位分隔,在python中统一用“\n”作为换行符进行分隔
23.4 二进制文件操作
- 模式:b
- 说明:
- 默认文件中存储的都是以字节为单位的数据,通常为人为的格式
- 对二进制文件的读写需要用字节串或字节数组进行操作;对于二进制文件读写方法都需要用字节为单位进行操作
23.5 F.seek方法
-
作用: 设置文件的读写设置,返回新的读写位置
-
格式:
F.seek(偏移量,whence=相对位置)
- 参数说明:
- 偏移量:大于0代表向文件末尾方向移动;小于0代表向文件头方向移动
- 相对位置:
- 0:代表从文件头开始偏移;
- 1:代表从当前读写位置开始偏移
- 2:代表从文件尾开始偏移
24 面向对象编程
24.1 面向对象技术简介
- 类:用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。
- 类变量:类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。
- 方法:类中定义的函数。
- 数据成员:类变量或者实例变量用于处理类及其实例对象的相关的数据。
- 方法重写:如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖,也称为方法的重写。
- 局部变量:定义在方法中的变量,只作用于当前实例的类。
- 实例变量:在类的声明中,属性是用变量来表示的,这种变量就称为实例变量,实例变量就是一个用self修饰的变量。
- 继承:即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。例如,有这样一个设计:一个Dog类型的对象派生自Animal类,这是模拟“是一个(is-a)”关系。
- 实例化:创建一个类的实例,类的具体对象。
- 对象:通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。
Python中的类提供了面向对象编程的所有基本功能:
- 类的继承机制允许多个基类
- 派生类可以覆盖基类中的任何方法
- 方法中可以调用基类中的同名方法。