property: -- 將裝飾過的函數(方法)變成類屬性,這樣的屬性須要經過 - @函數(方法).setter 纔可以直接修改這個屬性函數
class A: @property # 將fun函數變成了類的屬性 def fun(self): # 這兒只能有self參數 return self._a
@fun.setter # 這個屬性須要被setter才能直接修改屬性值 def fun(self, n): self._a = n
staticmethod: 將類的方法變成靜態方法 -- 將類中的函數參數self 變成普通參數工具
應用場景:當把一個模塊導入時,須要用到模塊中的某個類和某個函數 from module import cls, fun 這樣使用比較繁瑣性能
能夠將fun寫進cls類中,加上staticmethod裝飾器,就能經過cls.fun(argv) 調用,而又不會影響fun的功能開發工具
class A: @staticmethod def fun(self): # 這兒self不在是實例化屬性,變成普通參數了 print(self) a = A() a.fun(2) # 2被self接收
classmethod: 類裝飾器 -- 將類自己看成參數傳入函數中測試
class B: @classmethod def fun(cls): # cls = B自己 pass
本身構建的裝飾器spa
import functools def log(fn): @functools.wraps(fn) # 將fn的相關屬性複製到wrap def wrap(*args, **kwargs): print(f"decorator {fn}") return fn(*args, **kwargs) print(f"wrap: {id(wrap)}") print(f"fn: {id(fn)}") return wrap @log def guai(x: int, y: int): print(x + y) guai(1,5)
>>>
wrap: 4328403560 fn: 4328403424 decorator <function guai at 0x101fe31e0> 6
類型裝飾器code
def log(cls): class wraper: def __init__(self, *args, **kwargs): self.__dict__['inst'] = cls(*args, **kwargs)def __getattr__(self, item): print('here') print(item) return getattr(self.inst, item) def __setattr__(self, key, value): # 攔截x.a的複製操做 print('k:v', key, value) setattr(self.inst, key, value) #攔截後儲存到self.inst, 那麼查詢x.a也只能在self.inst中查到(經過__getattr__) return wraper @log class X: pass x = X() x.a = 100 print(x.__dict__) print(x.a)
>>>
k:v a 100 {'inst': <__main__.X object at 0x10cd704a8>} here a 100
裝飾器的應用場景:輔助開發工具(調用跟蹤,性能測試,內存檢測等任務),類能夠實現單例模式blog
簡單的統計調用次數:內存
def log(fn): def counter(*args, **kwargs): counter.__count__ += 1 return fn(*args, **kwargs) counter.__count__ = 0 return counter @log def run():pass for i in range(4): run() print(f"調用次數{run.__count__}") >>> 調用次數4
屬性管理:爲目標添加額外的屬性開發
def add_somethings(cls): cls.something = 1 cls.something1 = lambda x: [1,2,3,] return cls @add_somethings class A: pass print(A().something) print(A().something1()) >>> 1 [1, 2, 3]