如何理解python的裝飾器:讀《簡單 12 步理解 Python 裝飾器》筆記
筆記:
要想理解python裝飾器,需理解以下幾點(本人愚笨,需時刻提醒自己):
1、面向物件!時刻牢記python是面向物件的,python中,一切都是“物件(object)”
2、理解函式的定義和呼叫的區別,理解“賦值不等於呼叫”,理解“()”是“呼叫操作符”,參考下面的例子。
>>> def outer():
... def inner():
... print("Inside inner") # 1
... return inner
...
>> > foo = outer() # 2
>>> foo
<function outer.<locals>.inner at 0x10b6076a8>
>>> foo() # 3
Inside inner
看上面的程式碼:
#1 的位置,函式outer返回函式inner。函式inner的生命週期是依賴函式outer的,每次呼叫outer的時候,inner被重新定義,但如果函式outer沒有返回inner,則當超出函式outer的的作用域時,函式inner的生命週期將消失。
#2 的位置,通過函式呼叫操作符“()”,呼叫outer函式,獲得的是返回值inner,並賦值給變數foo,即inner函式的一個定義(說的白話文一些,就是獲得了一個指向inner函式例項的指標),但此時,並未呼叫inner函式
#3 的位置,通過函式呼叫操作符“()”,完成了對變數(物件)foo的“呼叫”!也就是說,完成了對函式inner的呼叫,inner函式開始執行,輸出列印結果。
3、閉包的概念,python支援一種名為“函式閉包”的特性,意味著“在非全域性作用域定義的函式,在定義時記得外層名稱空間是怎樣的”,還是結合上面的程式碼,說白了,就是函式inner記得定義它的外層函式outer的名稱空間裡的引數。
>>> def outer(x):
... def inner():
... print (x)
... return inner
. ..
>>> print1 = outer(1)
>>> print2 = outer(2)
>>> print1()
1
>>> print2()
2
4、裝飾器@:裝飾器其實就是“一個以函式作為引數並返回一個替換函式”的可執行函式。
5、*args和**kwargs
再次強調:
*表示對緊隨其後的迭代器的拆包;
**表示對緊隨其後的字典物件的拆包。
或者說:
*表示從緊隨其後的迭代器中取出相應的“位置引數”
**表示所有未捕獲的“關鍵字引數”,都將被儲存在緊隨其後的字典物件中。
>>> def logger(func):
... def inner(*args, **kwargs):
... print ("Arguments were: %s %s" % (args, kwargs))
... return func(*args, **kwargs)
... return inner
...
>>> @logger
... def foo1(x, y=1):
... return x*y
...
>>> @logger
... def foo2():
... return 2
...
>>> foo1(5, 4) # 位置實參的傳遞
Arguments were: (5, 4) {}
20
>>> foo1(x=5, y=4) #關鍵字實參的傳遞
Arguments were: () {'x': 5, 'y': 4}
20
>>> foo2()
Arguments were: () {}
2
>>>