參考
https://taizilongxu.gitbooks.io/stackoverflow-about-python/content/3/README.html
簡(jiǎn)單介紹下
- 裝飾器就是把其他函數(shù)作為參數(shù)的函數(shù)
def my_shiny_new_decorator(a_function_to_decorate):
def the_wrapper_around_the_original_function():
# 把要在原始函數(shù)被調(diào)用前的代碼放在這里
print "Before the function ru先簡(jiǎn)單ns"
# 調(diào)用原始函數(shù)(用括號(hào))
a_function_to_decorate()
# 把要在原始函數(shù)調(diào)用后的代碼放在這里
print "After the function runs"
return the_wrapper_around_the_original_function
- 裝飾器真實(shí)面紗
@my_shiny_new_decorator
def another_stand_alone_function():
print "Leave me alone"
another_stand_alone_function()
#輸出:
#Before the function runs
#Leave me alone
#After the function runs
就這么簡(jiǎn)單.@decorator就是下面的簡(jiǎn)寫:
another_stand_alone_function = my_shiny_new_decorator(another_stand_alone_function)
- 裝飾器里傳入?yún)?shù)
# 這不是什么黑魔法,你只需要讓包裝器傳遞參數(shù):
def a_decorator_passing_arguments(function_to_decorate):
def a_wrapper_accepting_arguments(arg1, arg2):
print "I got args! Look:", arg1, arg2
function_to_decorate(arg1, arg2)
return a_wrapper_accepting_arguments
# 當(dāng)你調(diào)用裝飾器返回的函數(shù)時(shí),也就調(diào)用了包裝器,把參數(shù)傳入包裝器里,
# 它將把參數(shù)傳遞給被裝飾的函數(shù)里.
@a_decorator_passing_arguments
def print_full_name(first_name, last_name):
print "My name is", first_name, last_name
print_full_name("Peter", "Venkman")
# 輸出:
#I got args! Look: Peter Venkman
#My name is Peter Venkman
- 裝飾方法
在Python里方法和函數(shù)幾乎一樣.唯一的區(qū)別就是方法的第一個(gè)參數(shù)是一個(gè)當(dāng)前對(duì)象的(self)
來點(diǎn)刺激的
把參數(shù)傳遞給裝飾器
- 先來看個(gè)
@decorator_maker()例子(相當(dāng)于decorated_function = decorator_maker()(decorated_function))
def decorator_maker():
print "I make decorators! I am executed only once: "+\
"when you make me create a decorator."
def my_decorator(func):
print "I am a decorator! I am executed only when you decorate a function."
def wrapped():
print ("I am the wrapper around the decorated function. "
"I am called when you call the decorated function. "
"As the wrapper, I return the RESULT of the decorated function.")
return func()
print "As the decorator, I return the wrapped function."
return wrapped
print "As a decorator maker, I return a decorator"
return my_decorator
@decorator_maker()
def decorated_function():
print "I am the decorated function."
#輸出:
#I make decorators! I am executed only once: when you make me create a decorator.
#As a decorator maker, I return a decorator
#I am a decorator! I am executed only when you decorate a function.
#As the decorator, I return the wrapped function.
#最終:
decorated_function()
#輸出:
#I am the wrapper around the decorated function. I am called when you call the decorated function.
#As the wrapper, I return the RESULT of the decorated function.
#I am the decorated function.
所以如果我們?cè)诤瘮?shù)運(yùn)行過程中動(dòng)態(tài)生成裝飾器,就可以把參數(shù)傳遞給函數(shù)
def decorator_maker_with_arguments(decorator_arg1, decorator_arg2):
print "I make decorators! And I accept arguments:", decorator_arg1, decorator_arg2
def my_decorator(func):
# 這里傳遞參數(shù)的能力是借鑒了 closures.
# 如果對(duì)closures感到困惑可以看看下面這個(gè):
# http://stackoverflow.com/questions/13857/can-you-explain-closures-as-they-relate-to-python
print "I am the decorator. Somehow you passed me arguments:", decorator_arg1, decorator_arg2
# 不要忘了裝飾器參數(shù)和函數(shù)參數(shù)!
def wrapped(function_arg1, function_arg2) :
print ("I am the wrapper around the decorated function.\n"
"I can access all the variables\n"
"\t- from the decorator: {0} {1}\n"
"\t- from the function call: {2} {3}\n"
"Then I can pass them to the decorated function"
.format(decorator_arg1, decorator_arg2,
function_arg1, function_arg2))
return func(function_arg1, function_arg2)
return wrapped
return my_decorator
@decorator_maker_with_arguments("Leonard", "Sheldon")
def decorated_function_with_arguments(function_arg1, function_arg2):
print ("I am the decorated function and only knows about my arguments: {0}"
" {1}".format(function_arg1, function_arg2))
decorated_function_with_arguments("Rajesh", "Howard")
#輸出:
#I make decorators! And I accept arguments: Leonard Sheldon
#I am the decorator. Somehow you passed me arguments: Leonard Sheldon
#I am the wrapper around the decorated function.
#I can access all the variables
# - from the decorator: Leonard Sheldon
# - from the function call: Rajesh Howard
#Then I can pass them to the decorated function
#I am the decorated function and only knows about my arguments: Rajesh Howard
但是一定要記住了裝飾器只能被調(diào)用一次.當(dāng)Python載入腳本后,你不可以動(dòng)態(tài)的設(shè)置參數(shù)了.當(dāng)你運(yùn)行import x,函數(shù)已經(jīng)被裝飾,所以你什么都不能動(dòng)了
最后來一個(gè)屌爆的線程安全單實(shí)例裝飾器
def singleton(cls):
instance = cls()
instance.__call__ = lambda: instance
return instance
#
# Sample use
#
@singleton
class Highlander:
x = 100
# Of course you can have any attributes or methods you like.
Highlander() is Highlander() is Highlander #=> True
id(Highlander()) == id(Highlander) #=> True
Highlander().x == Highlander.x == 100 #=> True
Highlander.x = 50
Highlander().x == Highlander.x == 50 #=> True
- 在定義class Highlander的時(shí)候已經(jīng)執(zhí)行完所有singleton裝飾器中的代碼,得到了一個(gè)instance,所以這之后所有對(duì)Highlander的調(diào)用實(shí)際上是在調(diào)用instance的call 方法。
- 我們通過lambda函數(shù)定義了call方法讓它始終返回instance,因此Highlander()和Highlander都返回instance
- 同時(shí)由于在類定義代碼執(zhí)行時(shí)就已經(jīng)創(chuàng)建了instance,所以后續(xù)不論是多線程還是單線程,在調(diào)用Highlander時(shí)都是在調(diào)用instance的call方法,也就無需同步了。
最后我想說的是這種方法簡(jiǎn)直碉堡了~~~