制心一处,无事不办
1.定义与原型
# 在不改变原有函数代码,且保持原函数调用方法不变的情况下,给原函数增加新的功能(或者给类增加属性和方法)
# 核心思想:用一个函数去装饰一个旧函数,造出一个新函数
# 语法规则:在原有的函数上加上@符号,装饰器会把下面的函数当作参数传递到装饰器中,@符又被称为语法糖
# 应用场景:引入日志,函数执行时间的统计,执行函数前的准备工作,执行函数后的处理工作,权限检验,缓存等场景中
# 定义外函数,接收一个函数作为参数
def outer(f):
# 定义一个内函数,并在内函数中调用了外函数的参数
def inner():
print(‘我是一个内函数1’)
f()
print(‘我是内函数2’)
**return **inner_
@outer # 此处使用的#outer的语法就是把outer作为了装饰器,等同于 old = outer(old)
def old():
print(‘我是一个普通函数’)
old() # 此时的old函数是经过outer装饰器装饰过的函数
2.统计函数执行时间
import time
#定义装饰器
def runtime(f):
def inner():
start = time.perf_counter()
f()
end = time.perf_counter() - start
print(f’共用了{end}秒’)
return inner
@runtime
def func():
for i in range(1,10):
print(i,end=‘ ‘)
time.sleep(0.5)
func()
3.语法
①装饰器的嵌套
#定义装饰器
def outer(f):
def inner():
print(‘找到妹子,成功拿下微信…’)
f()
print(‘约会…’)
return inner
#第二个装饰器
def kz(f):
def inner():
print(‘rrrr’)
f()
print(‘ggg’)
return inner
@kz
@outer
def love():
print(‘聊天…’)
love()
#先使用离得近的装饰器(下面的),装饰成为一个函数,这个函数再被第二个装饰器装饰
②装饰带有参数的函数
#定义装饰器
def outer(f):
#在内函数加上一个参数即可
def inner(name):
print(f’找到{name}妹子,成功拿下微信…’)
f(name)
print(f’约会{name}…’)
return inner
@outer
def love(name):
print(f’和{name}聊天…’)
love(‘杨幂’)
③装饰带有多参数的函数
def outer(f):
#内函数的参数需要和需要装饰的函数的参数相对应
def inner(who,name,args,kwargs):
print(‘约到妹子聊微信’**)
f(who,name,args,kwargs)
print(‘天色已晚,怎么办? 滚出我们五个九的直播间!’)
return **inner
@outer
def love(who,name,args,kwargs):
print(f’{who}跟{name}畅谈人生…’)
print(‘吃饭去了,吃了so many’,args)
print(‘看视频’*,kwargs)
love(‘任已虚’,‘杨幂’,‘牛肉干’,‘麻辣烫’,video = ‘快乐向前冲’)
④带有参数的装饰器
#如果你的装饰器需要有参数,那么给当前的装饰器套一个壳,用于接收装饰器的参数
def kuozhan(var):
def outer(f):
def inner1():
print(‘妹子给了你微信’)
f()
def inner2():
print(‘妹子给了你大逼兜’)
f()
#装饰器壳的参数,用于在函数内部去做流程控制
if var == ‘高富帅’:
return inner1
else:
return inner2
return outer
@kuozhan(‘臭屌丝’)
def love():
print(‘聊天’)
love()
⑤用类装饰器装饰函数
class Outer():
#魔术方法:当把该类的对象当作函数调用时,自动触发 obj()
def call(self,func):
self.func = func #把传经来的函数作为对象的成员方法
return self.inner #返回一个函数
#在定义的需要返回的新方法中,去装饰和处理
def inner(self,who):
print(‘拿到妹子的微信…’)
self.func(who)
print(‘看一场电影…’)
@Outer()
def love(who):
print(f’{who}和妹子聊天’)
love(‘旭旭宝宝’) #inner(‘旭旭宝宝’)
_print(love) #此时的love就是属于Outer类这个对象中的inner方法_
⑥用类方法装饰函数
class Outer():
def newinner(f):
Outer.func = f
return Outer.inner
def inner():
print(‘拿到妹子微信’)
Outer.func()
print(‘看电影’)
@Outer.newinner
def love():
print(‘聊天’)
love()