python裝飾器是在函數調用之上的修飾,這些修飾是在聲明或者定義一個函數的時候進行設置的。同時,裝飾器是一個返回函數對象的高級函數。裝飾器的語法是以@開頭的,而后是裝飾器函數的名字以及可選的參數,而后是裝飾器要修飾的函數以及該函數的可選參數,主要是以下形式:
@decorator(dec_opt_args)
def func2Bdecorator(func_opt_args):
......
1 裝飾器與函數類型
裝飾器類型
裝飾器有兩種形式,無參decorator以及有參decorator:
無參decorator
生成一個新的經過裝飾的函數,并用這個經過裝飾的函數代替原函數
有參decorator
裝飾函數首先處理傳入的decorator參數,并生成一個新的裝飾器函數,然后使用這個裝飾器函數對要被裝飾的函數進行裝飾
函數類型
同時函數又分為有參和無參兩種
無參函數
對于無參數的函數,并沒有什么需要特別注意的地方
有參函數
因為傳入裝飾器的函數是不定的,也就是說傳入的參數也是不定的,為了使裝飾器能對所有參數類型的函數進行處理,裝飾器中函數的參數有特殊處理,接下來會介紹
2 無參裝飾器-無參函數
def decorator_func(func):
def handle():
print "the function of %s begin ..." %func.__name__
func()
print "the function of %s end !" %func.__name__
return handle
@decorator_func
def say():
print "hello decorator!"
say( )
print say.__name__
上述代碼最后調用say函數的輸出如下:
the function of say begin ...
hello decorator!
the function of say end!
handle
decorator_func
是一個裝飾器(decorator),返回一個函數對象。上述代碼中,在定義say函數前加上了@decorator_func
之后,雖然say( )函數還是存在的,但是say
變量指向了由decorator_func
返回的handle
函數對象,于是在上述代碼的最后打印say
的函數名的輸出結果是handle
而不是say
。
3 無參裝飾器-有參函數
當需要修飾的函數帶有參數時,裝飾器的定義跟上述無參函數有一定的區別,主要為了讓裝飾器可以應對具有參數不同的各種函數
def decorator_func(func):
def handle(*args, **kwargs):
print "the function of %s begin ..." %func.__name__
func(*args, **kwargs)
print "the function of %s end !" %func.__name__
return handle
@decorator
def say(name = "world"):
print "hello %s!" %name
4 有參裝飾器-無參函數
當裝飾器帶有參數,也就是在原來裝飾器的基礎上再做一層封裝。代碼實現如下:
def decomaker_func(text):
def decorator_func(func):
def handle():
print "%s-->%s()!" %(text, func.__name__)
func()
return handle
return decorator_func
@decomaker_func("haha")
def say():
print "hello, decomaker!"
say()
上述代碼的輸出:
haha-->say()
hello, decomaker!
因裝飾器自身帶有參數,于是將其稱之為decomaker
,也就是上述定義中的第一層函數decomaker_func
,它的作用是返回一個decorator也就是第二層函數decorator_func
,這層函數的作用就是將封裝好的handle
函數賦值給say
變量。
5 有參裝飾器-有參函數
def decomaker_func(text):
def decorator_func(func):
def handle(*args, **kwargs):
print "%s-->%s(*args, **kwargs)!" %(text, func.__name__)
func(*args, **kwargs)
return handle
return decorator_func
@decomaker_func("haha")
def say(name = "decomaker"):
print "hello, %s!" %name
say()
輸出:
haha-->say(*args, **kwargs)
hello, decomaker!
6 給函數裝飾多個裝飾器
當一個函數由多個裝飾器進行裝飾時,其裝飾過程是有固定的順序的,比如如下的形式:
@d1
@d2(args)
@d3
def f():
等價于:
f = d1(d2(args)(d3(f)))