使用装饰器的目的是增加函数的功能,好处是不用破坏原函数的代码。应用场景诸如,本来你已经写好了某一个软件,突然某一天你上司跟你说要增加什么功能,这时候你又不能轻易修改其中一段函数的代码。那么,装饰器的出现在这个时候就显得很合时宜了。

构造装饰器的要诀是高阶函数加嵌套函数。高阶函数有两种:一种是将一个函数当做参数传递给另外一个参数,另外一种是将一个函数作为函数返回值传递给调用者,如下图所示



def haizi(func):
    func()

def play():
    pass


haizi(play)  #将play()当做haizi()的参数



def haizi():
    return play  #返回的是play()的内存地址

def play():
    pass


print(haizi())



理解高阶函数的关键是我们可以把函数看成是变量,这样我们就能理解一个函数为什么可以作为另外一个函数的参数或者返回值了。

嵌套函数是指在定义一个函数的时候在内部再定义一个函数,而不是调用某个函数,注意两者的区别,如:



def haizi():
    play()  #这是在haizi()内调用play()

def play():
    pass


haizi()



def haizi():
    def play():  #这是在haizi()内嵌套定义play()
        pass



理解高阶函数和嵌套函数之后,我们就可以构造一个简单的装饰器:



def haizi(func):  #高阶函数的运用,
    def play():  #在haizi()内嵌套定义play()
        func()           print("从前初识这世间")  #增加输出字符串功能
    return play  #高阶函数的运用

@haizi   #语法糖,放在被装饰的函数前面
def baby():
    pass

baby()



在上面代码中,语法糖@haizi的作用等价于baby = haizi(baby),因此func指向函数baby(),故而func()等价于baby()。此时,我们调用baby()时,除了执行baby()函数本身的功能外,还输出了一串中文。这是baby()函数没有参数的情况,当其有参数时,我们应该在



def haizi(func):  #高阶函数的运用,
    def play(*args):  #baby()的参数应该添加在这里,继而传给func()
        func(args)
        print("从前初识这世间")  #增加输出字符串功能
    return play  #高阶函数的运用

@haizi   #语法糖,放在被装饰的函数前面
def baby(str1):
    print("万般留恋 %s"% str1)

baby("看着天边似在眼前")



当装饰函数本身也有参数时,应该在原有基础上在最外层嵌套一个函数:



def young(num):
    def haizi(func):  #高阶函数的运用,
        def play(*args):  #baby()的参数应该添加在这里,继而传给func()
            func(args)
            print("从前初识这世间")  #增加输出字符串功能
            if num > 3 :
                print("也甘愿赴汤蹈火去走它一遍")
        return play  #高阶函数的运用
    return haizi

@young(6)  #注意此时这里不再是haizi了
def baby(str1):
    print("万般留恋 %s"% str1)


baby("看着天边似在眼前")



看到这里,你已经初识了装饰器的世间了,该出去历练了!