制心一处,无事不办
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()
