装饰器实际上就是一个方法,但是他可以修饰其他的方法或者类,我们定义好一个方法或者类,在他之前使用装饰器可以实现我们想要的效果,比如我们有许多方法都要进行打印日志,虽然我们可以每一个方法里面都写上打印日志,但这样会显得很麻烦,我们只需要定义好一个打印日志的方法,然后用修饰符调用装饰我们需要打印日志的方法和类就能实现,我们先从闭包开始理解
闭包
什么是闭包,就是在方法里面写方法,然后内部方法可以调用外部方法的变量,我们先来看一个闭包的实现
def funA():
a = 1
def inner():
print(a) #闭包内部可以调用外面的参数
return inner
funa = funA()
print(funa,funa.__name__) #打印结果,我们会发现他是一个function(函数,或者可以叫做方法),他的名字叫inner,__name__是内置参数,我们可以直接使用,既然是一个方法,我们就可以调用
funa() #打印结果:1 我们通过变量名直接调用方法
装饰器的定义
学习python我们知道函数也是一个对象,如果是对象就能被调用,那么我们把方法当成参数放在另一个方法中进行调用,我们可以通过方法调用方法
def funA(f):
f()
print(‘AAA‘)
def funB():
print(‘BBB‘)
funA(funB) #打印结果 BBB AAA
我们会发现funB替换了f参数被调用了,如果我们funB想要传入参数怎么办,这时我们就要用到上面的闭包了
def funA(f):
print(‘哈哈‘)
def inner(*args,**kwargs): #*args是通过元组的方式传入,**kwargs是通过dict的方式传入,
print(‘刚进入函数‘)
f(*args,**kwargs) #上面的闭包中我们已经知道了可以调用外面的变量
print(‘离开函数‘)
print(‘嘻嘻‘)
return inner
def funB(*args,**kwargs):
print(args,kwargs)
print(‘BBB‘)
funa = funA(funB) #打印结果:哈哈 嘻嘻 我们在上面可以看到返回的是一个方法,我们用funa变量接收,这个就是inner函数
funa(1,2,3,name=‘tom‘,age=18) #打印结果:刚进入函数 (1,2,3) {‘name‘:‘tom‘,‘age‘:18} 离开函数 调用inner函数了把参数传入
我们的funcB会替换f(*args,**kwargs),我们通过inner函数把参数传入了funB中,这样就实现了我们的函数调用函数,我们定义的其他的方法也可以在funA进行调用来实现我们需要的效果,funA就是一个装饰函数,在python中用了一个修饰符来代替我们的执行过程,通过@就能实现装饰器的使用,我们需要把装饰器定义在函数之前,如果装饰器下面没有函数就会报错
@funA
def login(*args,**kwargs):
print(‘登陆成功‘)
我们在这里就已经实现了装饰器的调用,他已经完成了装饰器外层的打印 # 打印结果:哈哈 嘻嘻
login(name=‘tom‘,pwd=‘123‘) #(1,2,3) {‘name‘:‘tom‘,‘age‘:18}
这样就定义好了装饰器,我们要注意的是这里已经实现了变量名称的一个转换,调用过程我们可以看做是把inner()函数的变量名变成了login,login()函数的变量名已经变成了f,我们只是把参数通过inner()传入到了f()中,我们可以做一个判断用户是否存在的装饰器
def has_user(func):
user = {‘name‘:‘tom‘,‘pwd‘:‘123‘}
def inner(*args,**kwargs):
name = kwargs[‘name‘]
pwd = kwargs[‘pwd‘]
if name == user[‘name‘] and pwd == user[‘pwd‘]:
print(‘用户存在‘)
func(*args,**kwargs)
else:
print(‘用户不存在‘)
return inner
@has_user
def login(*args,**kwargs):
print(‘登录成功了‘)
login(name=‘tom‘,pwd=‘123‘) #打印结果:用户存在 登陆成功
原文:https://www.cnblogs.com/llm123456/p/11878338.html