decorator

參考
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í)例裝飾器

參考http://www.itdecent.cn/p/ec6589e02e2f

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)直碉堡了~~~
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容