1. 程式人生 > >對 Python 裝飾器的理解心得

對 Python 裝飾器的理解心得

原文連結:http://www.cnblogs.com/ifantastic/archive/2012/12/09/2809325.html

  1. 什麼是裝飾器?

  顧名思義,裝飾器就是在方法上方標一個帶有@符號的方法名,以此來對被裝飾的方法進行點綴改造。

  當你明白什麼是裝飾器之後,自然會覺得這個名字取得恰如其分,但作為初學者來說多少還是會有些迷茫。下面用程式碼來說明怎麼理解裝飾器。

複製程式碼
#指令碼1
def target(): print('this is target') def decorator(func): func() print('this is decorator') decorator(target) ------------------------------------------- 執行結果為: this is target this is decorator
複製程式碼

  Python允許將方法當作引數傳遞,因此以上指令碼就是將target方法作為引數傳入decorator方法中,這其實也是裝飾器的工作原理,以上程式碼等同於:

複製程式碼
#指令碼2
def decorator(func): func() print('this is decorator') @decorator def target(): print('this is target') target ------------------------------------------- 執行結果: this is target this is decorator
複製程式碼

  因此可以看出,所謂的裝飾器就是利用了Python的方法可作引數傳遞的特性,將方法target作為引數傳遞到方法decorator中。

@decorator
def target():
    ...

  這種在一個方法的上方加一個@符號的寫法,就是表示位於下方的方法將被作為引數傳遞到位於@後面的decorator方法中。使用@符號只是讓指令碼1中的程式碼換了一個寫法,更加好看,當然也會更加靈活與實用,後面會講到這點。但它們的本質其實是一樣的,這也就是裝飾器的工作原理。

  2. 裝飾器的原理

  如果你仔細看的話,會在指令碼2中發現一個問題,那就是指令碼2中最後一行的target只是一個方法名字,它不是正確的方法呼叫,正確寫法應該加上左右括號的target(),如下:

複製程式碼
#指令碼3

def decorator(func):
    func()
    print('this is decorator')

@decorator
def target():
    print('this is target')

target()
--------------------------------------------
執行結果:

this is target
this is decorator
Traceback (most recent call last):
  File "C:/Users/Me/Desktop/ff.py", line 34, in <module>
    target()
TypeError: 'NoneType' object is not callable
複製程式碼

   正如你所看到的,如果按照正確的寫法,執行結果你會看到應該出現的兩行列印文字"this is target"和"this is decorator",還會出現錯誤提示,ff.py是我為寫這篇心得臨時編寫的一個py指令碼名字,提示說'NoneType'物件不可呼叫。這是怎麼回事?好吧,我現在必須告訴你,其實指令碼2和指令碼3中並不是一個使用裝飾器的正確寫法,不是使用錯誤,而是作為裝飾器的decorator方法寫的並不友好,是的,我不認為它是錯誤的寫法,只是不友好。但只要你明白其中的道理,使用恰當的手段也是可以執行正常的,這就是為什麼指令碼2看似寫錯了呼叫方法卻得出了正確的結果。當然學習還是得規規矩矩,後面我會具體說正確的裝飾器怎麼書寫,在這裡我先解釋了一下指令碼2和指令碼3的執行原理,瞭解它們的執行原理和錯誤原因,其實就是了解裝飾器的原理。

  指令碼2和指令碼3的區別在於target和target(),也就是說真正的差別在於()這個括號。當()被附加在方法或者類後面時,表示呼叫,或者稱為執行及例項化,無論稱呼怎樣,本質意義沒有不同,都是呼叫給出的物件,當物件不具備呼叫性的時候,就會報錯:'某個型別' object is not callable。當一個方法被呼叫後,即target(),是否能被再次執行,取決於它是否會return一個物件,並且該物件可以被呼叫。也許你會有點迷糊,對比一下程式碼會比較容易理解我想表達的意思:

複製程式碼
 1 >>>def returnme():
 2 >>>    print('this is returnme')
 3  
 4 >>>def target():
 5 >>>    print('this is target')
 6   
 7 >>>target
 8 <function target at 0x00000000030A40D0>
 9   
10 >>>target()
11 target
12 <function returnme at 0x00000000030A4268>
13  
14 >>>target()()
15 target
16 returnme
17 
18 >>>returnme()()
19 returnme
20 Traceback (most recent call last):
21   File "<pyshell#15>", line 1, in <module>
22     returnme()()
23 TypeError: 'NoneType' object is not callable
複製程式碼

  如上所示,當直接在指令碼中輸入target,它只是告訴編譯器(我想是編譯器吧,因為我也不是很懂所謂編譯器的部分),總之就是告訴那個不知道在哪個角落控制著所有python程式碼執行的“大腦”,在

0x00000000030A40D0位置(這個位置應該是指記憶體位置)存有一個function(方法)叫target;在target後面加上(),表示呼叫該方法,即輸入target(),“大腦”便按照target方法所寫的程式碼逐條執行,於是打印出了target字串,並且“大腦”明白在0x00000000030A4268位置有一個叫returnme的方法;因為target物件呼叫後是會返回一個returnme方法,並且方法是可以被呼叫的,因此你可以直接這樣書寫target()(),“大腦”會逐條執行target中的程式碼,然後return一個returnme,因為多加了一個(),表示要對返回的returnme進行呼叫,於是再次逐條執行returnme中的程式碼,最後便能看到15、16的列印結果;而returnme方法是沒有返回任何可呼叫的物件,因此當輸入returnme()()時,“大腦”會報錯。

  下面我們可以來解釋一下指令碼2和指令碼3的執行詳情,之前說過,裝飾器的工作原理就是指令碼1程式碼所演示的那樣。

複製程式碼
@decorator
def target():
    ...
等同於
def decorator(target)(): ...

注:python語法中以上寫法是非法的,以上只是為了便於理解。
複製程式碼

  當你呼叫被裝飾方法target時,其實首先被執行的是作為裝飾器的decorator函式,然後“大腦”會把target方法作為引數傳進去,於是:

複製程式碼
#指令碼2
def decorator(func):
    func()
    print('this is decorator')
  
@decorator
def target():
    print('this is target')
  
target
-------------------------------------------

實際執行情況:
首先呼叫decorator方法:decorator()
因為decorator方法含1個引數,因此將target傳入:decorator(target)
執行程式碼“func()”,根據傳入的引數,實際執行target(),結果打印出:this is target
執行程式碼"print('this is decorator')",結果打印出:this is decorator
複製程式碼

   對比指令碼3的執行情況:

複製程式碼
#指令碼3
def decorator(func):
    func()
    print('this is decorator')
  
@decorator
def target():
    print('this is target')
  
target()
-------------------------------------------

實際執行情況:
首先呼叫decorator方法:decorator()
因為decorator方法含1個引數,因此將target傳入:decorator(target)
執行程式碼“func()”,根據傳入的引數,實際執行target(),結果打印出:this is target
執行程式碼"print('this is decorator')",結果打印出:this is decorator

以上與指令碼2中執行情況完全相同,接下來便是執行指令碼2中target沒有的(),也就是執行呼叫命令。
由於decorator(target)沒有返回一個可以被呼叫的物件,因此“大腦”提示錯誤:'NoneType' object is not callable
複製程式碼

  如果你還不是很清楚,請看下面的等價關係:

複製程式碼
@decorator
def target():
    ...

等同於
def decorator(target)():
    ...

因此:
target == decorator(target)
target() == decorator(target)()

所以:
假設有一個變數var=target,在將target賦值給var時,其實是將decorator(target)的呼叫結果賦值給var,因為var不具備呼叫性(not callable),因此執行var()時,編譯器會報錯它是個NoneType物件,不能呼叫。
複製程式碼

   綜上所述,你大概已經能夠明白所謂的裝飾器是怎麼一回事,它是怎麼工作的。但指令碼2和指令碼3中的寫法會帶來一些困惑,這個困惑就是通過我們編寫的decorator裝飾器對target進行裝飾後,將target變成了一個永遠不能被呼叫的方法,或者說變成了一個呼叫就報錯的方法。這跟我們的使用習慣以及對方法的認識是很不協調的,畢竟我們還是習慣一個方法天生註定可以被呼叫這種看法。所以為了滿足我們對方法的定義,我們最好將作為裝飾器的方法寫成一個可以返回具有被呼叫能力的物件的方法。

複製程式碼
#指令碼4
def whatever(): print('this is whatever') def decorator(func): func() print('this is decorator') return whatever  #1 @decorator def target(): print('this is target') ------------------------------ 輸入:target 結果: this is target this is decorator 輸入:target() 結果: this is target this is decorator this is whatever
複製程式碼

  在#1的位置,你可以return任何可以被呼叫的方法或類,甚至你可以直接寫成:

複製程式碼
def whatever():
    print('this is whatever')

def decorator(func):
    return whatever

@decorator
def target():
    print('this is target')

------------------------------
輸入:target
結果:告訴編譯器在記憶體某個位置有一個叫whatever的方法

輸入:target()
結果:this is whatever
複製程式碼

  以上裝飾器的作用就是將target方法,完完全全變成了whatever方法。但這隻能完美解釋裝飾器的功效,在實際當中則毫無意義,為什麼要辛辛苦苦寫了一大堆程式碼之後,最後的結果卻是完完整整地去呼叫另一個早已存在的方法?如果要呼叫whatever方法,我為什麼不在我的程式碼中直接寫whatever呢?

  裝飾器,顧名思義,它就是要對被裝飾的物件進行一些修改,通過再包裝來達到不一樣的效果,儘管它可以將被裝飾物件變得面目全非或者直接變成另一個物件,但這不是它被髮明出來的主要意義,相反它被髮明出來是幫助我們更高效更簡潔的編寫程式碼,對其他方法或類進行裝飾,而非摧毀它們。例如對接收資料的檢校,我們只要寫好一個校驗方法,便可以在其他許多方法前作為裝飾器使用。

  3. 常規的裝飾器

  從廣義上來說,裝飾器就是指令碼1中,利用python可以將方法傳參的特性,用一個方法去改變另一個方法,只要改變成功,都可以認為是合格的裝飾器。但這是理論上的合格,畢竟裝飾器是一種語法糖,應該是為我們帶來便利而不是無用功,所以:

複製程式碼
1. 將方法裝飾成不能被呼叫,不好:
def decorator(func):
    func()
    print('this is decorator')

2. 將原方法徹底消滅,直接變成另一個方法,不好:
def decorator(func):
    return whatever

3. 保留原方法的同時再加上別的功能,不好:
def decorator(func):
    func()
    print('this is decorator')
    return whatever
複製程式碼

  在以上3種寫法中,前兩種明顯不好,簡直就是將裝飾器變成了惡魔。而第3種寫法,雖然看起來重新包裝了被修飾方法,但卻在方法呼叫前擅自執行了一些命令,即當你輸入target,而非target()時:

複製程式碼
#指令碼4
def whatever():
    print('this is whatever')

def decorator(func):
    func()
    print('this is decorator')
    return whatever  #1

@decorator
def target():
    print('this is target')

------------------------------
輸入:target
結果:
this is target
this is decorator
複製程式碼

  你尚未執行target(),編譯器卻已經列印了兩行字串。這並不是我們想要的,當我們在程式碼中寫下target時,我們是不希望編譯器立即執行什麼命令,我們是希望編譯器在碰到target()時才執行運算。而且如果我們並不希望返回whatever,我們只想要通過裝飾器,使得target方法除了列印自己的"this is target",再多列印一行"this is decorator”,所有程式碼只含有target和decorator兩個方法,無其他方法介入,應該怎麼辦?

  當你這樣問的時候,其實就是已經開始瞭解裝飾器存在的意義了。以下便是為解決這些問題的裝飾器的常規寫法:

複製程式碼
#指令碼5

def decorator(func):
    def restructure():    
        func()
        print('this is decorator')
    return restructure

@decorator
def target():
    print('this is target')
複製程式碼

  是的,從最外層講,以上程式碼其實只有兩個方法,decorator和target——裝飾和被裝飾方法。但在decorator內部內嵌了一個方法restructure,這個內嵌的方法才是真正改造target的東西,而decorator其實只是負責將target傳入。這裡的restructure,相當於在指令碼4中,被寫在decorator外面的whatever角色,用裝飾器的常規寫法也可以寫出指令碼4的效果,如下:

複製程式碼
def decorator(func):   
    func()
    print('this is decorator')

    def whatever():
        print('this is whatever')     
    return restructure

@decorator
def target():
    print('this is target')
複製程式碼

   對比以上的寫法你會發現,python的方法傳參和類的繼承性質很相似,在decorator之內,whatever之外,你可以寫入任何程式碼,當執行target時,就開始初始化decorator,也就是執行decorator內部可以執行的程式碼;當執行target()時,會對初始化之後的decorator開始呼叫,因此這就要求decorator完成初始化之後必須返回一個具備呼叫性的物件。所以,除非你想要target方法初始化之前(實際上是對decorator進行初始化)就執行一些程式碼,否則不要在decorator和whatever中間插入程式碼。

  正常情況下,當decorator完成初始化,應該return一個可呼叫物件,也就是指令碼5中的restructure方法,這個方法就是替代target的克隆人,在restructure中你可以對target進行重寫,或其他程式碼來包裝target。因此你只是想初始化target的話(實際就是對restructure初始化),就應將你要初始化的程式碼寫入到restructure內部去。另外你也可以在decorator中內嵌多個方法,或多層方法,例如:

複製程式碼
#指令碼6

def decorator(func):
    def restructure():    
        func()
        print('this is decorator')

    def whatever():
        func()
        print('this is whatever')

    return restructure

@decorator
def target():
    print('this is target')
複製程式碼

  被decorator裝飾的target最後會多列印一行'this is decorator'還是'this is whatever’,取決於decorator方法return的是它內部的哪一個方法(restructure或whatever),因此以上程式碼等價於以下寫法:

複製程式碼
執行target()

等同於

首先初始化decorator(target),結果返回一個restructure,即:target == decorator(target) == restructure。

然後呼叫,即:target() == decorator(target)() == restructure()

與類一樣,當target被傳入decorator之後,作為decorator內嵌方法是可以呼叫(繼承)target方法的,這就是為什麼restructure不用接受傳參就可以改造target的原因。

注:在python中,以上多個()()的寫法是非法的,這樣寫只是為了便於理解。
複製程式碼

  裝飾器這個概念本來也可以設計成多個()這樣的形式,但這樣就破壞了python的基本寫法,而且不好看,尤其當有多重灌飾的時候,因此使用@置於方法前的設計是更加優雅和清晰的。

  我之所以使用多個()這樣並不被python支援的寫法來闡述我對python的裝飾器的理解,是因為我相信通過這樣被python放棄的語法也能更好地幫助你理解python的繼承、傳參以及裝飾器,尤其是帶有引數的裝飾器。

  4. 裝飾帶有引數的方法

  首先請看以下程式碼:

複製程式碼
def target(x):
    print('this is target %s'%x)

def decorator(func,x):
    func(x)
    print('this is decorator %s'%x)

decorator(target,'!')

等同於:

def decorator(func):
    def restructure(x):
        func(x)
        print('this is decorator %s'%x)
    return restructure

@decorator
def target(x):
    print('this is target %s'%x)

target('!')
複製程式碼

  target(x)中的引數x是如何傳入,什麼時候傳入裝飾器的?首先嚐試以下程式碼:

複製程式碼
def decorator(func):
    print(x)  #增加一行程式碼
    def restructure(x):
        func(x)
        print('this is decorator %s'%x)
    return restructure

@decorator
def target(x):
    print('this is target %s'%x)

target('!')
複製程式碼

  此時編譯器會報錯引數x沒有被定義,也就是說在初始化decorator的時候,只有target方法被傳入,其引數x='!'並沒有傳入。

  現在讓我們回顧一下之前說的裝飾器工作原理,如下:

複製程式碼
target == decorator(target) == restructure。

target() == decorator(target)() == restructure()

同理:

target(x) == decorator(target)(x) == restructure(x)
複製程式碼

  所以,你可以很清楚地瞭解到,作為target的引數,其實不是傳給decorator,而是傳給初始化完decorator之後return的restructure。因此,如果裝飾器寫成如下程式碼: 

def decorator(func):
    def restructure():    #不帶引數的方法
        func(x)
        print('this is decorator %s'%x)
    return restructure

  此時你輸入target('!'),編譯器會告訴你restructure沒有引數,但被傳入了1個引數,這個被傳入的引數就是x='!'。

  所以你現在明白了被裝飾的方法target(x),方法target和引數x是如何被傳入的,所以你必須保證初始化decorator之後返回的物件restructure方法形參與被裝飾的target方法形參相匹配,即:

如果定義為:def target(x)
則裝飾器中:def restructure(x)

如果定義為:def target(x,y)
則裝飾器中:def restructure(x,y)

  你也許會發現如果想裝飾器同時裝飾target(x)和newtarget(x,y),以上寫法就無法滿足要求了。因此為了讓裝飾器可以適用於更多的物件,我們最好讓裝飾器寫成如下形式:

複製程式碼
def decorator(func):
    def restructure(*x):
        func(*x)
        print('this is decorator')
    return restructure

@decorator
def target(x):
    print('this is target %s'%x)

@decorator
def newtarget(x,y):
    print('this is target %s%s'%(x,y))

target('!')
newtarget('!','?')
複製程式碼

  利用python的帶星號引數語法(*arg),你便可以傳入任意數量的引數,你也可以設定帶雙星號的形參(**arg),便可以傳入字典形式的引數,單星形參和雙星形參可以同時使用,如:def restructure(*arg, **arg)。

  5. 帶有引數的裝飾器

  只要記住以上的裝飾器工作原理,你便可以知道如何寫出帶有引數的裝飾器,如:

複製程式碼
def newdecorator(i):
    def decorator(func):
        def restructure(x):
            func(x)
            print('this is decorator %s%s'%(i,x))
        return restructure
    return decorator

@newdecorator('?')
def target(x):
    print('this is target %s'%x)

target('!')
-------------------------------------------------------
結果:
this is target !
this is decorator ?!
複製程式碼

  以上程式碼實際上是:

target(x) == newdecorator(i)(target)(x) == decorator(target)(x) == reconstructure(x)

  同理,為了滿足不同數量的引數傳入,你也可以將newdecorator(i)寫成newdecorator(*i, **ii)。

  6. 結束語

  只要明白裝飾器的設計原理,便可以自如地寫出想要的裝飾器,哪怕是多重、多引數的裝飾器。

相關推薦

Python 裝飾理解心得

原文連結:http://www.cnblogs.com/ifantastic/archive/2012/12/09/2809325.html   1. 什麼是裝飾器?   顧名思義,裝飾器就是在方法上方標一個帶有@符號的方法名,以此來對被裝飾的方法進行點綴改造。

Python裝飾理解

python裝飾器 高階函數 out 發現 分享 打印 內部 存儲 -i 本文介紹Python其中一個強大的功能--裝飾器 裝飾器本質上就是一個函數,在不修改源代碼,調用方法的前提下,用來給其他函數添加功能的函數 想象一下,你已經開發完成一個功能,並且投入應用中,卻發

Python 裝飾理解與使用

Python裝飾器 本質是函式 為其他函式新增附加功能。裝飾器本身也是Python的一個重點,所以無論如何你必須弄懂它。裝飾器的存在其實就是為了在需要新增新功能時不影響之前版本的使用的同時來增加新功能,其實也是一種“偷懶”的辦法。它的使用場景較多,比如:插入日誌、效能測試、事務處理、快取

python 裝飾理解

文章先由stackoverflow上面的一個問題引起吧,如果使用如下的程式碼: @makebold @makeitalic def say():      return"Hello" 打印出如下的輸出: <b><i>

Python-裝飾以及帶有引數的裝飾理解

請編寫一個decorator,能在函式呼叫的前後打印出’begin call’和’end call’的日誌。 再思考一下能否寫出一個@log的decorator,使它既支援: @log def f(): pass 又支援: @log('e

python-裝飾,類與象,私有字段,析構,__call__,繼承,多繼承,接口

裝飾器 類與對象 私有字段 析構 __call__ 繼承 1、裝飾器執行流程裝飾器:將原函數替換為wrapper函數def outer()@outer --- func1作為參數傳入outer()def wrapper() --- wrapper()放入內存return wrapp

python裝飾實現異常代碼出現進行監控

args lin sha lines 監控腳本 一秒 readline utf 發送 異常,不應該存在,但是我們有時候會遇到這樣的情況,比如我們監控服務器的時候,每一秒去采集一次信息,那麽有一秒沒有采集到我們想要的信息,但是下一秒采集到了, 而

Python裝飾的通俗理解

python 裝飾器 python裝飾器 在學習Python的過程中,我相信有很多人和我一樣,對Python的裝飾器一直覺得很困惑,我也是困惑了好久,並通過思考和查閱才能略有領悟,我希望以下的內容會對你有幫助,我也努力通過通俗的方式使得對Python裝飾器的理解更加的透徹,很多人對裝飾器難以理解,

如何理解python裝飾

() 如何 lee 簡單的 存在 port print pytho -s 如何理解裝飾器python 學習遇到的第一個難點是裝飾器。裝飾器的作用是不大規模改動代碼的情況下,增加功能。作用:為已經存在的對象添加額外的功能特點:不需要對對象做任何的代碼上的變動。以一個例子來講裝

python裝飾三種裝飾模式的簡單理解

學設計模式中有個裝飾模式,用java實現起來不是很難,但是遠遠沒有python簡單,難怪越來越火了! 這裡就簡單討論下python的幾種裝飾模式: 一 無參裝飾器: # 裝飾器 import time # 裝飾器,記錄函式執行時間 def decorator01(fun): def w

Python 裝飾@,函式進行功能擴充套件,開閉原則

裝飾器可以對原函式進行功能擴充套件,但還不需要修改原函式的內容(開閉原則),也不需要修改原函式的呼叫。   demo.py(裝飾器,@): # 閉包 def w1(func): def inner(): # 對原函式進行功能擴充套件 pr

理解 Python 裝飾看這一篇就夠了

講 Python 裝飾器前,我想先舉個例子,雖有點汙,但跟裝飾器這個話題很貼切。 每個人都有的內褲主要功能是用來遮羞,但是到了冬天它沒法為我們防風禦寒,咋辦?我們想到的一個辦法就是把內褲改造一下,讓它變得更厚更長,這樣一來,它不僅有遮羞功能,還能提供保暖,不過有個問題,這個內褲被我們改造成了

理解Python裝飾

裝飾器本質上是一個函式,該函式用來處理其他函式,它可以讓其他函式在不需要修改程式碼的前提下增加額外的功能,裝飾器的返回值也是一個函式物件。它經常用於有切面需求的場景,比如:插入日誌、效能測試、事務處理、快取、許可權校驗等應用場景。裝飾器是解決這類問題的絕佳設計,有了裝飾器,我們就可以抽離出大

Python裝飾為什麼難理解

無論專案中還是面試都離不開裝飾器話題,裝飾器的強大在於它能夠在不修改原有業務邏輯的情況下對程式碼進行擴充套件,許可權校驗、使用者認證、日誌記錄、效能測試、事務處理、快取等都是裝飾器的絕佳應用場景,它能夠最大程度地對程式碼進行復用。 但為什麼初學者對裝飾器的理解如此困難,我認為本質上是對Pyt

12步教你理解Python裝飾

或許你已經用過裝飾器,它的使用方式非常簡單但理解起來困難(其實真正理解的也很簡單),想要理解裝飾器,你需要懂點函數語言程式設計的概念,python函式的定義以及函式呼叫的語法規則等,雖然我沒法把裝飾器變得簡單,但是我希望可以通過下面的步驟讓你由淺入深明白裝飾器是什麼。假定你擁有最基本的Pyt

python裝飾測試與理解

第一,裝飾器基礎語句 # 這是一個基本的裝飾器測試檔案 def deco(func): def mod(): func() print("I'm mod") #mod函式在接收的func函式基礎上,後置增加

[轉]理解Python裝飾

作者:xlzd 連結:http://www.zhihu.com/question/26930016/answer/81263287 來源:知乎 著作權歸作者所有。商業轉載請聯絡作者獲得授權,非商業轉載請註明出處。簡單來講,可以不嚴謹地把Python的裝飾器看做一個包裝函式的函式。比如,有一個函式:def fu

如何理解Python裝飾

Python 裝飾器使用非常地簡單。任何會使用 Python 函式的人都可以學習使用裝飾器: Python 123@somedecoratordefsome_function():print("Check it out, I

python裝飾的簡單理解

1、裝飾器是什麼? 裝飾器,顧名思義,就是用來“裝飾”的。 它長這個樣: @func_name 它能裝飾的東西有:函式、類 2,為何需要裝飾器? 先來打個比方,內褲可以用來遮羞,但是到了冬天它沒法為我們防風禦寒,聰明的人們發明了長褲,有了長褲後寶寶再也不冷了,裝飾器就

如何理解python裝飾:讀《簡單 12 步理解 Python 裝飾》筆記

原文:簡單 12 步理解 Python 裝飾器 筆記: 要想理解python裝飾器,需理解以下幾點(本人愚笨,需時刻提醒自己): 1、面向物件!時刻牢記python是面向物件的,python中,一切都是“物件(object)” 2、理解函式的定義和呼叫的區別,理解“賦值不等於呼叫