基于前面的使用函數(shù)作為裝飾器的理解,將類作為裝飾器時需要保證以下幾點
- 類的實例是可調用的
- 類需要一個地方講被裝飾的函數(shù)傳入到類的實例里
第一條可以通過__call__實現(xiàn),第二條可以通過__init__實現(xiàn)。
手工將類作為裝飾器使用
class Profiled:
def __init__(self, func):
# wraps(func)(self)
self.func = func
def __call__(self, *args, **kwargs):
print("call")
return self.func(*args, **kwargs)
def add(x, y):
return x + y
add = Profiled(add)
result = add(1, 2)
print(result)
執(zhí)行結果:
call
3
似乎再用語法糖包裝一下就可以實現(xiàn)將類作為裝飾器來使用了。
使用類作為裝飾器使用
from functools import wraps
class Profiled:
def __init__(self, func):
# wraps(func)(self)
self.func = func
def __call__(self, *args, **kwargs):
print("call")
return self.func(*args, **kwargs)
@Profiled
def add(x, y):
return x + y
result = add(1, 2)
print(result)
運行結果同上。
小結
這節(jié)我們以我們理解的方法實現(xiàn)了將類作為裝飾器使用,看起來都很正確,似乎就是這樣使用?但是這種方法還有一些別的問題,最重要的是同樣的問題,可以在代碼中使用:
print(add.__name__)
發(fā)現(xiàn)無法輸出__name__,根據(jù)約定使用裝飾器不能改變函數(shù)的__name__屬性,因此我們還需要改進將類作為裝飾器的使用方法。