Python裝飾器

Python裝飾器

  • 裝飾器的功能和實現方法
    • 功能:對函數和類功能進行擴展
    • 裝飾模式有不少經典的使用場景,例如插入日誌、性能測試、事務處理等等,有了裝飾器,就能夠提取大量函數中與自己功能無關的相似代碼,從而達到代碼重用的目的。
    • 實現:裝飾器能夠是函數,也能夠是一個對象,總之是能夠將要裝飾的函數做爲參數傳入並返回函數或對象再賦值給函數或類
    • 裝飾器語法糖:在Python中,可使用」@」語法糖來精簡裝飾器的代碼
    • 下面使用不一樣的方式實現裝飾器來講明:
# 使用裝飾器函數裝飾函數
def decorator(func):
    print(func)
    #這就是將來的demo函數
    def inner():
        print('執行demo函數以前增長一些功能')
        func()
        print('執行demo函數以後增長一些功能')
    #返回內部函數做爲將來的demo函數
    return inner

# 語法糖,使用decorator函數來裝飾demo函數,至關於demo = decorator(demo)
@decorator
def demo():
    print('測試裝飾器的函數')
    return 0

demo()
複製代碼
<function demo at 0x000001D3146CE158>
執行demo函數以前增長一些功能
測試裝飾器的函數
執行demo函數以後增長一些功能
複製代碼
# 實現帶有參數和返回值的裝飾器
def decorator(func):
    print(func)
    #這就是將來的demo函數(原函數有什麼形參,這裏就要有什麼形參)
    def inner(var):
        print('執行demo函數以前增長一些功能')
        res = func(var)
        print('執行demo函數以後增長一些功能')
        return res
    #返回內部函數做爲將來的demo函數
    return inner

# 使用decorator函數來裝飾demo函數
@decorator
def demo(var):
    print('測試裝飾器的函數')
    return var

test = demo('測試')
print(test)
複製代碼
<function demo at 0x000001D3146EE048>
執行demo函數以前增長一些功能
測試裝飾器的函數
執行demo函數以後增長一些功能
測試
複製代碼
# 帶有參數的裝飾器(給裝飾器加參數,根據不一樣的參數實現不一樣的擴展功能)
def outer(arg):
    
    def decorator(func):
        print(func)
        #這就是將來的demo函數(原函數有什麼形參,這裏就要有什麼形參)
        def inner1(var):
            print('執行demo函數以前增長一些功能1')
            res = func(var)
            print('執行demo函數以後增長一些功能1')
            return res
        def inner2(var):
            print('執行demo函數以前增長一些功能2')
            res = func(var)
            print('執行demo函數以後增長一些功能2')
            return res
        if arg == 1 :
            #返回內部函數做爲將來的demo函數
            return inner1
        elif arg == 2 :
            return inner2
    return decorator

# 使用decorator函數來裝飾demo函數,參數爲1
# outer(1) 返回的是函數decorator,
# 此操做等同於 demo = outer(1)(demo) --> demo = decorator(demo)[arg = 1]
@outer(1)
def demo(var):
    print('測試裝飾器的函數')
    return var

test = demo('測試')
print(test)

print('\n###############################################\n')
# 使用decorator函數來裝飾demo函數,參數爲2
# outer(2) 返回的是函數decorator,
# 此操做等同於 demo = outer(2)(demo) --> demo = decorator(demo)[arg = 2]
@outer(2)
def demo(var):
    print('測試裝飾器的函數')
    return var

test = demo('測試')
print(test)
複製代碼
<function demo at 0x000001D3146CE840>
執行demo函數以前增長一些功能1
測試裝飾器的函數
執行demo函數以後增長一些功能1
測試

###############################################

<function demo at 0x000001D314702B70>
執行demo函數以前增長一些功能2
測試裝飾器的函數
執行demo函數以後增長一些功能2
測試
複製代碼
# 將類做爲裝飾器使用
class decorator:
    # 初始化魔術方法
    def __init__(self,arg):
        self.arg = arg
    
    # 當對象被當作函數調用時觸發
    def __call__(self,func):
        self.func = func
        return self.inner
    # 裝飾函數
    def inner(self,var):
        print('執行demo函數以前增長一些功能2')
        res = self.func(var)
        print('執行demo函數以後增長一些功能2')
        return res
        
# 實例化類decorator,將實例化後的對象做爲函數使用
# 等同於demo = decorator(1)(demo) --> demo = decorator(1).__call__(demo)
# 必需要存在的函數,__init__()用於接收@decorator(1) 中的1,
# __call__()用於實現將對象當作函數調用的功能,須要接收demo函數
# __inner__()函數,用來裝飾demo函數的裝飾函數
@decorator(1)
def demo(var):
    print(var)
    return var
    
res = demo('123')
print(res) 
複製代碼
執行demo函數以前增長一些功能2
123
執行demo函數以後增長一些功能2
123
複製代碼
# 使用裝飾器實現類的單例模式,爲類添加裝飾器
objs = {}
# 須要接收的參數是類,能夠對多個類實現單例模式
def decorator(cls):
    #裝飾函數,返回cls類型的對象
    def inner():
        obj = None
        if cls in objs:
            return objs[cls]
        else :
            obj = object.__new__(cls)
            objs[cls] = obj
        return obj
    return inner

# 只要在類上加上裝飾器就能夠實現單例模式
@decorator
class demo1:
    pass

@decorator
class demo2:
    pass

# 實例化兩個demo1類型的對象,輸出兩個對象的id是相同的,單例模式實現
t1 = demo1()
t2 = demo1()
print(id(t1),id(t2))

# 實例化兩個demo2類型的對象,輸出兩個對象的id是相同的,單例模式實現,其餘要實現單例模式的類只要加上裝飾器便可
t21 = demo2()
t22 = demo2()
print(id(t21),id(t22))
複製代碼
2006092685552 2006092685552
2006092688128 2006092688128
複製代碼
# 多個裝飾器嵌套
#裝飾器1
def decorator1(func):
    def inner():
        print('裝飾器1')
        func()
        print('裝飾器1')
    return inner

# 裝飾器2
def decorator2(func):
    def inner():
        print('裝飾器2')
        func()
        print('裝飾器2')
    return inner

# 先使用裝飾器1對demo進行裝飾,再使用裝飾器2對demo進行裝飾
# 等同於 demo = decorator1(demo),demo = decorator2(demo)
@decorator2
@decorator1
def demo():
    print('demo函數')
demo()
複製代碼
裝飾器2
裝飾器1
demo函數
裝飾器1
裝飾器2
複製代碼

總結

  • 裝飾器本質上是一個python函數,它可讓其餘函數在不作任何代碼變更的前提下增長額外的功能,裝飾器的返回值也是一個函數對象
  • python內置的三個裝飾器:staticmethod,classmethod和property
    • staticmethod:把類中的方法定義爲靜態方法,使用staticmethod裝飾的方法可使用類或者類的實例對象來調用,不須要傳入self
    • classmethod:把類中的方法定義爲類方法,使用classmethod裝飾的方法可使用類或者類的實例對象來調用,並將該class對象隱式的做爲第一個參數傳入
    • property:把方法變成屬性
  • 三種內置裝飾器之後再詳述
相關文章
相關標籤/搜索