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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 func
6 happy = name(happy)
7 happy()
8 print(happy.__name__,name.__name__,)
mumu
be happy
happy name

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

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

1 def name(func):
2     print(mumu)
3     return func
4 @name
5 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
@name
def happy(user):
    print(%s be happy% user)
    return "ye!"
ret = happy(must)
print(返回值:,ret)
mumu
must 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 inner
14 
15 @outer2
16 @outer1
17 def happy():
18     print (happy everyday)
19 
20 happy()

 

o2,before
o1,before
happy everyday
o1,after
o2,after

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

 

 

 

以上是关于Python自学之路——装饰器的秘密的主要内容,如果未能解决你的问题,请参考以下文章

python之路-11-装饰器

NO.4:自学python之路------内置方法装饰器迭代器

python之路---15 装饰器

python之路--装饰器函数

Python自学之乐-装饰器浅谈

Python学习之路6 - 装饰器