1. 程式人生 > >如何理解python的裝飾器:讀《簡單 12 步理解 Python 裝飾器》筆記

如何理解python的裝飾器:讀《簡單 12 步理解 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
>>>