裝飾器

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]
相關文章
相關標籤/搜索