最近看了下老男孩的关于python 装饰器的讲解,这里记录下自己的理解要看原文的请戳这里
预备知识
首先看下面代码
def f1():
print("123")
def f1():
print("456")
f1
f1()
IDLE中打印结果如下:
>>> f1
<function f1 at 0x04DE3270>
>>> f1()
456
>>>
从这里可以看到2点
- 函数名 代指函数内部的代码(我的理解是这样~)
- 函数名() 这样的形式python才会执行python代码
再看下面代码
def outer(func): #1
def inner():
print("before")
ret = func()
print("after")
return ret #4
return inner
@outer #2
def f1(): #2
print("f1")
f1() #3
@函数名 就表示这是一个装饰器,以上面为例子,他有如下2个功能
- 自动执行 outer函数,并将其下面的函数名f1作为参数传入@后面的函数即outer(f1)
- 将@ 后面函数outer(f1)的返回值重新赋值给下面的函数f1 —-即f1 = outer(f1)的返回值 就是这里的作用
#2处会调用outer(f1),而在outer里面又定义了一个inner函数,现在只是定义,并没有执行,所以紧接着会执行 return inner
把inner返回了,返回给了谁?看第2点,返回给了f1,则此时新f1=inner,来看下新f1的函数体代码是什么,就是outer里面定义的inner函数
print("before")
ret = func()
print("after")
return ret
其实这里的func就是老f1函数体代码,即
print("f1")
注意这里只是定义了,并没有执行
当有人在外面调用了f1 即#3处,现在才执行了inner里面的代码,效果如下
before
f1
after
#4处是为了f1可能有返会值,这里不能影响被装饰函数的执行效果
如果被装饰函数有参数,个数还能确定怎么办呢?
可以用万能参数,通过outer传进去,如下:
def outer(func):
def inner(*arg,**kwargs):
print("before")
ret = func(*arg,**kwargs)
print("after")
return ret
return inner
@outer
def f1(*arg,**kwargs):
print("f1")
f1()
还有,一个函数可以被多个装饰器装饰吗?
可以的,如下代码
def outer2(func):
def inner(*arg,**kwargs):
print("before2")
ret = func(*arg,**kwargs)
print("after2")
return ret
return inner
def outer1(func):
def inner(*arg,**kwargs):
print("before1")
ret = func(*arg,**kwargs)
print("after1")
return ret
return inner
@outer2
@outer1
def f1(*arg,**kwargs):
print("f1")
f1()
执行效果如下:
before2
before1
f1
after1
after2