装饰器
一、装饰器的特点
特点: 1.函数A作为参数出现(函数B接受函数A作为参数) 2.有闭包的特点。
def decorate(func): #定义一个装饰器,函数作为参数
a=100
def wrapper():
func()
print("----->刷漆")
print("----->铺地板")
print("----->装门")
return wrapper
#使用装饰器:@+函数名,装饰函数
@decorate
def house():
print('我是毛胚房。。。')
house()
二、装饰器的流程
1.house被装饰函数 2.将被装饰器函数传给装饰器函数 3.执行decorate函数 4.将返回值赋值给house 总而言之,就是先将被装饰的函数作为实参传给装饰器,然后执行装饰器函数,在装饰器函数中执行相应代码,如果遇到内部函数就加载它,但是没有调用,然后返回内部函数,这个内部函数赋值给被装饰函数,此时这个被装饰函数名,已经等同于装饰器内部函数,用被装饰函数名+()时则在调用内部函数wrapper(),而wrapper已经加载,在执行时会调用一看是传进来的func函数(实则为原来的被装饰函数)。
def decorate(func): #定义一个装饰器
a=100
print("wrapper外层打印测试")
def wrapper():
func()
print("----->刷漆")
print("----->铺地板")
print("----->装门")
print("wrapper加载完成")
return wrapper
#使用装饰器:@+函数名,装饰函数
@decorate
def house():
print('我是毛胚房。。。')
print(house) #<function decorate.<locals>.wrapper at 0x000001BD64FA65F0>
#此时house就是wrapper
#house()
三、装饰器修饰多个函数
为了使装饰器可以装饰更多的函数,我们使用可变长度参数(*args和**kwargs) *args 和**kwargs
import time
#登录校验
def decorate(func):
def wrapper(*args,**kwargs): #可变长度参数 ()元组
print('正在校验中...')
time.sleep(2)
print("校验完毕。。。")
func(*args,**kwargs) #调用原函数
return wrapper
@decorate
def f1(n):
print("-----f1------",n)
f1(5) #此时的f1已经是wrapper了,没有参数
@decorate
def f2(name,age):
print("-----f2------",name,age)
f2('jone',18)
@decorate
def f3(students,clas='2020'):
print("{}班级的学生如下:".format(clas))
for stu in students:
print(stu)
f3(['Amy','Jhon','Tom'],clas='2024')
@decorate
def f4():
print("------>f4")
f4()
四、多层装饰器
我们可以对一个函数进行多层装饰,就像一个房子装修了一遍还可以再装修一遍。那么怎么做了?具体可以参照代码和函数的递归思想来理解。
def zhuang1(func):
print("------->1 start")
def wrapper(*args,**kwargs):
func()
print("刷漆")
print("-------->1 end")
return wrapper
def zhuang2(func):
print("-------->2 start")
def wrapper(*args,**kwargs):
func()
print("铺地板,装门.........")
print("-------->2 end")
return wrapper
@zhuang2
@zhuang1 #离得近的先装饰
def house():
print("毛胚房!.......")
house()
五、装饰器的参数
装饰器本质上是一个函数,所以我们在使用的时候也可以传参数进去。
def outer(a): #第一层 负责接收装饰器参数
def decorate(func): #第二层;负责接受函数
def wrapper(*args,**kwargs): #第三层:负责接受函数的参数
func(*args)
print("------>铺地板{}块".format(a))
return wrapper
return decorate
@outer(a=10)
def house(time):
print("我{}日期拿到房子的钥匙,是毛胚房。。。".format(time))
house('2025-6-11')
@outer(100)
def street():
print("新修的街道名字是:逸尘路")
street()
六、装饰器的应用
#开发:登录验证
import time
islogin=False #默认没有登录
#定义一个登录函数
def login():
username=input("请输入用户名:")
password=input("输入密码:")
if username=='admin' and password=='admin':
return True
else:
return False
#定义装饰器,进行付款验证
def login_required(func):
def wrapper(*args,**kwargs):
global islogin
print("-----付款------")
#验证用户是否登录
if islogin:
func(*args,**kwargs)
else:
#跳转登录页面
print("用户没有登录不能付款:")
islogin=login()
print("result: ",islogin)
return wrapper
@login_required
def pay(money):
print("正在付款,付款金额是:{}元".format(money))
time.sleep(2)
print("付款完成!")
pay(10000)
pay(8000) #此时islogin状态改变为ture,可以付款。
|