关于装饰器的详细描述在PEP-318有详尽的描述
https://www.python.org/dev/peps/pep-0318/
装饰器是在函数调用之上的修饰,这些修饰是仅当声明一个函数或者方法时才会应用的额外调用。
装饰器以@开头,接着是装饰器的名字和可选的参数,紧接着装饰器声明的是被修饰的函数和装饰函数的可选参数。看起来是这样样子
@decorator (dec_opt_args)
def func2Bdecorated (func_opt_args):
pass
了解修饰器之前,我们先来了解下他是如何产生的。当静态方法和类方法在2.2被加入到python时,实现是这样的:
class MyClass (object):
def staticFoo ():
pass
staticFoo = staticmethod(staticFoo)
def 后面跟着一行staticFoo = staticmethod(staticFoo)是有多臃肿,但是如果引入装饰器,就可以这样替换上面的代码:
class MyClasss (object):
@staticmethod
def staticFoo():
pass
大概你已经猜到装饰器的基本使用方法了,我们再来看一个例子:
@g
@f
def foo():
pass
如果用数学组合来表示的话,他就是这样的:(g · f) (x) = g( f(x) )。因此上面的代码等价于:
def foo():
pass
g( f(foo) )
装饰器的语法开始的确会让人觉得凌乱,原因就在于什么时候使用带参数的装饰器,在没有参数的情况下,一个装饰器看起来十分简单:
@deco
def foo():
pass
很直接的知道他相当于
def foo():
pass
foo = deco(foo)
但如果是带有参数的装饰器呢:
@deco1(deco_args)
def foo():
pass
它相当于:
def foo():
pass
foo = deco1(deco_args)(foo)
实际上deco1接受了deco_args参数然后返回一个函数对象,这个函数对象就是foo真正的装饰器。简单来说,我们可以把deco1(deco_argc)看成一个整体,用deco来代替,这样就变成了上面那个不带参数的装饰器,然后这个deco的装饰器实际是一个函数执行后的返回对象,不过这都不重要了。如果你理解上面的技巧,我们再把这个例子变化一下:
@deco1(deco_arg)
@deco2
def func():
pass
相当于:
deco1(deco_arg)(deco2(func))
其实就这么简单,像数学函数一样,嵌套嵌套嵌套。
说了这么久,那么到底什么是装饰器?装饰器实际就是一个接受函数对象为参数的函数。看几个装饰器例子,
1.定义一个退出程序时执行的函数
def onexit(f):
import atexit
atexit.register(f)
return f
@onexit
def func():
...
# -*- coding:gbk -*-
'''示例3: 使用语法糖@来装饰函数,相当于“myfunc = deco(myfunc)”
但发现新函数只在第一次被调用,且原函数多调用了一次'''
def
deco(func):
print
(
"before myfunc() called."
)
func()
print
(
" after myfunc() called."
)
return
func
@deco
def
myfunc():
print
(
" myfunc() called."
)
myfunc()
myfunc()