首页 > 代码库 > Python自学之路——装饰器的秘密

Python自学之路——装饰器的秘密

先不管装饰器到底是个什么东东,让我们来聊一聊函数的几个点吧。我们知道,在python里,一切皆是对象,那么函数呢,当然也是对象,而且人家还是一级对象呐。既然是对象,那它就可以被赋值给变量,反之,通过变量也能调用函数。好,需特别注意的点来了,函数调用一定是函数名 + (),如果没有这个括号,函数是不会被调用的,它只能是表示内存里的一个地址,看下面

1 def happy():2     print(be happy)3 print (happy) #并没有调用happy函数,只是打印了happy的地址4 happy() #调用happy函数
<function happy at 0x0000014B53C1F048>be happy

我们再来看一下函数作为变量被赋值的例子

技术分享

对于happy函数,如果我想在be happy这句前加个名字,该怎么办呢?理所当然的,我们会这样加

1 def happy():2     print(mumu)3     print(be happy)

可是,我们有没有想过,这样的话我们就破环了原来happy这个函数,并且,如果需要修改的函数量大一点,难不成我们还得一个个进去改吗?这种场景肯定是不允许的,于是,我们又琢磨出了一种方法……

1 def happy():2     print(be happy)3 def name(func):4     print(mumu)5     return func6 happy = name(happy)7 happy()8 print(happy.__name__,name.__name__,)
mumube happyhappy name

有没有发现,上面代码中最神奇的一句就是 happy = name(happy) ,通过这句话,python将happy的地址传给了name函数,让name函数执行它的代码(即增加一个名字)然后返回happy的地址,最后调用happy。这样,我们在没有改变happy函数的前提下实现了需求,是不是很厉害呢?其实,这就是装饰器的秘密!

然而,人家既然是装饰器,肯定不会是这样和别的代码一样样的啊,看好了,人家的形式可是这样的呢 @+函数名     让我们看一下用了真正装饰器的代码长什么样吧

1 def name(func):2     print(mumu)3     return func4 @name5 def happy():6     print(be happy)7 happy()8 print(happy.__name__,name.__name__,)

千万不要以为装饰器是如此简单噢,上一个稍微难一点的例子吧,借这个例子让我们好好捋一下装饰器在python解释器的原理

技术分享

我们再来看一下下面两个程序的区别

 

技术分享

写到这里,是不是发现我们都还没有参数的装饰器呢,给函数加个参数让我们来看看

def name(func):    def inner(arg):        print(mumu)        return  func(arg)    return inner@namedef happy(user):    print(%s be happy% user)    return "ye!"ret = happy(must)print(返回值:,ret)
mumumust be happy返回值: ye!

例子只是简单给了一个参数,如果你想要多个参数,甚至是多个不同类的参数,就用万能参数*args,**kwargs呗

现在我们应该明白,其实装饰器就是在原函数外面套了一层函数,使我们在调用原函数的时候调用的是装饰器返回给你的函数,那么,我们就想了,装饰器可以多个吗,一个一个地往函数上套?答案是肯定的,就看一下两个装饰器的例子吧,其实我觉得的吧,多个装饰器没必要,搞得那么复杂……

 

 1 def outer1(func): 2     def inner(): 3         print (o1,before) 4         func() 5         print (o1,after) 6     return inner 7  8 def outer2(func): 9     def inner():10         print (o2,before)11         func()12         print (o2,after)13     return inner14 15 @outer216 @outer117 def happy():18     print (happy everyday)19 20 happy()

 

o2,beforeo1,beforehappy everydayo1,aftero2,after

对于这种多个装饰器我们可以理解为它像俄罗斯套娃一样,最里面的原始函数被外面的装饰器函数一层一层地嵌套,原始函数的函数名传递给最靠近它的装饰器,里层的装饰器返回值会传递给外层装饰器的参数。

 

 

 

Python自学之路——装饰器的秘密