一、枚举
1.枚举类的特点
1. Python枚举作为一个类存在,使用它需要首先导入枚举模块,然后继承并自定义需要的枚举类;
2. 导入枚举模块可以是Enum(枚举值可以是任意类型),也可以是IntEnum(枚举值只能是整型);
3. 枚举类不允许存在相同的标签;但是允许不同标签的枚举值相同,这样后者相当于前者别名;
4. 不同的枚举类型,即使枚举名和枚举值都一样,比较结果也是False
2.定义枚举类
定义枚举类,需要在类的参数中,继承父类Enum
3.获取枚举类型、名字、值、遍历
from enum import Enum,IntEnum,unique
# 定义枚举类,需要在类的参数中,继承父类Enum
class VIP(Enum):
# 定义多个常量
YELLOW = 1
GREEN = 2
BLACk = 3
RED = 4
class Common():
YELLOW = 1
# 获取枚举类型
print(VIP.GREEN)
print(type(VIP['GREEN']))
# 获取枚举的名字
print(VIP.GREEN.name)
# 获取枚举的值
print(VIP.GREEN.value)
# 遍历枚举
for x in VIP:
print(x)
结果
VIP.GREEN
<enum 'VIP'>
GREEN
2
VIP.YELLOW
VIP.GREEN
VIP.BLACk
VIP.RED
4.与普通类相比
枚举类和普通类相比,普通类的变量是可变的,并且没有防止相同标签的功能
class Common():
YELLOW = 1
# 普通类变量,可变
Common.YELLOW = 2
print(Common.YELLOW)
结果
2
5.枚举类,注意事项
同一个枚举下,可以做is比较,以及相等比较,在不同枚举不可以比较
# 错误写法,不可以比较
# result = VIP.GREEN > VIP.BLACk
# 正确写法,可比较
result = VIP.GREEN == VIP.BLACk
print(result)
结果
False
同一个枚举下面,变量名不可以相同,变量值可以相同,# 值相同的情况下,YELLOW_ALIAS为YELLOW的别名
class VIP(Enum):
# 注:同一个枚举下面,变量名不可以相同,变量值可以相同,
# 值相同的情况下,YELLOW_ALIAS为YELLOW的别名
YELLOW = 1
YELLOW_ALIAS = 1
BLACk = 3
RED = 4
# 打印枚举中的3个变量,YELLOW_ALIAS不会被打印
for x in VIP:
print(x)
# 打印枚举中的4个变量,去掉items方法,只打印变量名
for y in VIP.__members__.items():
print(y)
# 将变量转换成枚举类
a = 3
print(VIP(a))
结果
VIP.YELLOW
VIP.BLACk
VIP.RED
('YELLOW', <VIP.YELLOW: 1>)
('YELLOW_ALIAS', <VIP.YELLOW: 1>)
('BLACk', <VIP.BLACk: 3>)
('RED', <VIP.RED: 4>)
VIP.BLACk
6.限制枚举类出现不同类型、不同值
# unique装饰器,限制变量出现相同值
@unique
# 继承IntEnum父类,限制变量出现不同类型
class VIP(IntEnum):
YELLOW = 1
YELLOW_ALIAS = 1
BLACk = 3
RED = 4
结果:执行报错,因为出现相同值
二、函数式编程
1.闭包
1.当函数环境变量,不受外部全局变量的影响,这就是闭包
def ch(x):
def ci(y):
c = x * y * y
return c
return ci
a = ch(25)
print(a(2))
# 闭包 = 函数 + 环境变量
# 当函数环境变量,不受外部全局变量的影响,这就是闭包
# 例如:环境变量 x =25,不受外部全局x=10的影响,而计算结果发生改变
x = 10
def curve_pre():
x = 25
def curve(y):
c = x * y * y
return c
return curve
f = curve_pre()
print(f(2))
# 闭包的环境变量保存在__closure__中
print(f.__closure__)
# 打印x当前的值
print(f.__closure__[0].cell_contents)
结果
100
100
(<cell at 0x107327bb0: int object at 0x1071c43f0>,)
25
2.普通函数与闭包的区别
嵌套函数中,一个变量被认为是局部变量,而不是环境变量,那么就不算闭包,使用__closure__方法,可以查看函数是否是闭包,返回None那就不是不是闭包
def f1():
a =10
def f2():
# a是一个局部变量,不是环境变量,所以不是闭包
a =20
return a
return f2
f = f1()
print(f())
print(f.__closure__)
结果
20
None
注意:判断是不是闭包,可以使用__closure__方法,返回None时就不是闭包
3.事例说明闭包作用
事例:实现一个步数增加的场景,如果不使用global关键字,执行会报错。但是使用global关键字,就不是闭包了
增加global关键字,origin为全局变量
1.闭包只会对内部环境变量发生改变,不会影响到全部变量sum
2.每调用一个函数,闭包会保存上一次执行获取的值
# 闭包只会对内部环境变量发生改变,不会影响到全部变量sum
sum = 0
def factory(pos):
def go(step):
# 使用nonlocal关键字,使pos成为环境变量
nonlocal pos
new_pos = pos + step
pos = new_pos
return new_pos
return go
s = factory(sum)
# 每调用一个函数,闭包会保存上一次执行获取的值
# 执行结果返回2,5,10
print(s(2))
print(s(3))
print(s(5))
print(sum)
结果
2
5
10
0
2.匿名函数及三元函数的使用
1.匿名函数及三元函数
匿名函数,使用lambda关键字
注:匿名函数一般在后面都是使用表达式
# 匿名函数的使用
# 注:匿名函数一般在后面都是使用表达式
a = lambda x,y : x + y
print(a(8,9))
结果
17
# 匿名函数与三元表达式结合适用于三元函数:条件为真时返回的结果 if 条件判断 else 条件为假时的返回结果
# 匿名函数与三元表达式结合适用于
# 三元函数:条件为真时返回的结果 if 条件判断 else 条件为假时的返回结果
b = lambda x,y : x if x>y else y
print(b(8,7))
结果
8
2.匿名函数与map方法的使用
打印列表中平方值
使用for循环打印和使用map方法打印
list_x = [1,2,3,4,5,6,7,9]
def square(x):
return x * x
for x in list_x:
print(square(x))
r = map(square,list_x)
print(list(r))
结果
1
4
9
16
25
36
49
81
[1, 4, 9, 16, 25, 36, 49, 81]
匿名函数、map方法结合使用
使用map方法,单个参数和多个参数的使用
注:多个参数时,输出结果长度会使用最少字符串的列表传值
# map方法返回map类型
list_a = [1,2,3,4,5,6,7,9]
list_b = [3,4,5,6,7,9]
# 使用map方法,单个参数和多个参数的使用
a = map(lambda x : x*x,list_a)
print(list(a))
# 注:多个参数时,输出结果长度会使用最少字符串的列表传值
b = map(lambda x,y : x*y+x,list_a,list_b)
print(list(b))
结果
[1, 4, 9, 16, 25, 36, 49, 81]
[4, 10, 18, 28, 40, 60]
3.匿名函数与reduce方法的使用
# reduce方法返回值
a = []
for i in range(1,101):
# 1到100追加成列表
a.append(i)
# 通过reduce方法,结合lambda匿名函数,完成相加
r = reduce(lambda x,y:x+y,a)
print(r)
b = ['ab','ac','ad','ae']
# 通过reduce方法,结合lambda完成相加,后面的10为初始化值
r = reduce(lambda x,y: x+y,b,str(10))
print(r)
结果
5050
10abacadae
4.匿名函数与filter方法的使用
# filter方法使用,抽取所有的1
list_x = [1,0,1,0,1,1,0]
r = filter(lambda x: True if x==1 else False,list_x)
print(list(r))
# filter方法使用,抽取所有的大写字母
list_y = ['a','B','c','D','E','F','g']
q = filter(lambda x : True if x.isupper() else False,list_y)
print(list(q))
# filter方法使用,抽取所有的小写字母
q = filter(lambda x : True if x.islower() else False,list_y)
print(list(q))
结果
[1, 1, 1, 1]
['B', 'D', 'E', 'F']
['a', 'c', 'g']
三、装饰器
1.装饰器的使用,简化调用时的代码
不使用装饰器,打印Hello world!
# 使用嵌套函数调用,打印“你好,世界!”
def decorator(func):
def wrapper():
for x in range(1,4):
print(str(x) + '——Hello world!')
func()
return wrapper
def f1():
print('你好,世界!')
# 没有使用装饰器调用函数
r = decorator(f1)
r()
结果
1——Hello world!
你好,世界!
2——Hello world!
你好,世界!
3——Hello world!
你好,世界!
使用装饰器打印Hello world!
def decorator(func):
def wrapper():
for x in range(1,4):
print(str(x) + '——Hello world!')
func()
return wrapper
# 通过装饰器先调用decorator
@decorator
def f2():
print('你好,wode世界!'*3)
# 使用装饰器调用
f2()
结果
1——Hello world!
你好,wode世界!你好,wode世界!你好,wode世界!
2——Hello world!
你好,wode世界!你好,wode世界!你好,wode世界!
3——Hello world!
你好,wode世界!你好,wode世界!你好,wode世界!
2.可变参数的情况下使用装饰器
import time
def Log_structure (func):
# *args可变参数
def log_time(*args):
print(time.time())
func(*args)
return log_time
@Log_structure
def Log_content01(log01,log02):
print('This is log 01:'+ log01)
print('This is log 02:'+ log02)
Log_content01('error','success')
结果
1656075871.8154051
This is log 01:error
This is log 02:success
3.可变参数+关键字参数情况下使用装饰器
*args可变参数+**kw关键字参数情况下使用装饰器
def Log_structure (func):
# *args可变参数+**kw关键字参数
def log_time(*args,**kw):
print(time.time())
func(*args,**kw)
return log_time
@Log_structure
def Log_content01(log01,log02,**log03):
print('This is log 01:'+ log01)
print('This is log 02:'+ log02)
print(log03)
Log_content01('error','success',Log_content = 'uncertain',long_content1 = 'uncertain1')
结果
1656075871.815507
This is log 01:error
This is log 02:success
{'Log_content': 'uncertain', 'long_content1': 'uncertain1'}
4.注意事项
1、使用可变参数和关键字参数,参数命名可根据具体需求变更
2、使用可变参数和关键字参数,调用时,可以随意使用任何参数
3、装饰器不仅可以简化代码,还可以是一个控制器