1. 程式人生 > >類裝飾器

類裝飾器

code 自動調用 其他 pan 實例對象 高內聚 一個 附加 spa

  在理解類裝飾器之前,先回憶一下有關裝飾器的知識。裝飾器本質上就是一個函數,它可以讓其他函數在不需要做任何代碼變動的前提下增加額外的功能,裝飾器的返回值也是一個函數對象(函數的引用)。

__call__方法
  一個對象是否可調用,看其中是否實現了__call__方法。例如,類的對象是不可調用的,因為其中沒有實現__call__方法。如果我們在一個類中定義了__call__方法,那麽這個類對象將變得可調用。只要某個對象定義了__call__()方法,那麽這個對象就是callable的。

類中沒有實現__call__方法:
>>> class A:    # 類中沒有實現__call__方法
... pass >>> a = A() >>> a() # 類對象不可調用 Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: A object is not callable 類中實現了__call__方法: >>> class B: ... def __init__(self): ... self.name = zhangsan ...
def __call__(self): # 類中實現了__call__方法 ... print(類中實現了__call__方法:, self.name) ... >>> b = B() >>> b() # 類對象可調用,並在調用類對象的時候,自動執行__call__方法 類中實現了__call__方法: zhangsan

類裝飾器
  類裝飾器本質上和函數裝飾器原理、作用相同,都是為其它函數增加額外的功能。但是相比於函數裝飾器,類裝飾器具有靈活度大、高內聚、封裝性等優點。使用類裝飾器可以直接依靠類內部的__call__方法來實現,當使用 @ 形式將類裝飾器附加到函數上時,就會調用類裝飾器的__call__方法。而不需要向函數裝飾器那樣,在裝飾器函數中定義嵌套函數,來實現裝飾功能。


  使用類裝飾器為一個函數的執行增加計時功能。

>>> import time
>>> class Foo():
...     def __init__(self, func):    # 初始化函數中傳入函數對象的參數
...         self._func = func
...     def __call__(self):    # 定義__call__方法,直接實現裝飾功能
...         start_time = time.time()
...         self._func()
...         end_time = time.time()
...         print(花費了 %.2f % (end_time - start_time))
... 
>>> @Foo  # bar=Foo(bar)
... def bar():
...     print(bar函數的執行時間為:)
...     time.sleep(2.5)
... 
>>> bar()    # bar=Foo(bar)(),沒有嵌套關系了,直接執行Foo的 __call__方法,實現裝飾功能   
bar函數的執行時間為:
花費了 2.51
  上面的@Foo相當於bar = Foo(bar),等號左邊的bar是類Foo的實例對象,等號右邊的bar是類裝飾器所裝飾的函數名bar作為參數傳遞給類Foo。下面執行bar()即為調用類Foo的對象bar,此時會自動調用類中定義的__call__方法。

類裝飾器