首页 > 代码库 > 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自学之路——装饰器的秘密