【Python】函數裝飾器、類裝飾器的實現

什麼是裝飾器

裝飾器本身是一個函數 ,作用是爲現有存在的函數,在不改變函數的基礎上去增加一些功能進行裝飾,裝飾器是通過閉包的形式實現的。
我另一篇博客:☞閉包的實現原理,如何在內部函數修改外部函數的變量

函數萬能裝飾器

這個裝飾器只是一種形式,沒有實際意義。

# 定義萬能函數裝飾器
def outFunc(func):
    # 接收不同的參數
    def wrapper(*args, **kwargs):
        print('萬能裝飾器')
        # 再原樣傳回給被裝飾的函數
        return func(*args, **kwargs)

    return wrapper

# 進行裝飾
@outFunc
def addNmu(a,b):

    return a+b
# 調用被裝飾的addNum函數
print(addNmu(3,4))

# 執行效果
# 萬能裝飾器
# 7

類裝飾器

實現方法:在類中通過使用 __init__和 __call__方法來實現,__init__接收要被裝飾的函數,__call__實現具體的裝飾內容。
類裝飾器也是用來裝飾函數的。
一切都在代碼中:

class Test(object):
    # 通過初始化方法,將要被裝飾的函數傳進來並記錄下來
    def __init__(self, func):
        self.__func = func

    # 重寫 __call__ 方法來實現具體裝飾內容
    def __call__(self, *args, **kwargs):
        print('類的裝飾器實現')
        self.__func(*args, **kwargs)

def show():
    print('i am func show')
    
# 裝飾前,show是一個函數
show()

# 裝飾後,show變成了Test類的實例對象
test1 = Test(show)
test1()
#------------------------------------------------------
# 執行效果
# 裝飾前
# i am func show
# 裝飾後
# 類的裝飾器實現
# i am func show

有沒有注意到__call__方法

__call__方法:Python中,只要在創建類的時候定義了__call__方法,這個類就是可調用的。
什麼意思呢?通過幾段代碼來看:

class Call(object):
    n = 1

# 實例化對象    
test2 = Call()
print(test2.n)

# 結果
# 1

思考,我們能不能像調用函數一樣使用類對象呢?

class Call(object):
    n = 1
    
test2 = Call()
print(test2())

運行結果:
在這裏插入圖片描述
錯誤提示,Call不能被調用;加入call方法:

class Call(object):

    def __call__(self, *args, **kwargs):
        n = 1
        return n
    
test2 = Call()
print(test2())

# 運行結果
# 1

結論

是不是感覺有點多此一舉?我們在這裏是爲了理解__call__方法的作用:

  • Python中的所有東西都是對象,其中包括Int/str/func/class這四類,它們都是對象,都是從一個類創建而來的。
  • 爲了將一個類實例當做函數調用,我們需要在類中實現__call__()方法。
  • 最重要的一點,前面類裝飾器的實現就是藉助__call__方法實現的。

補充

__new__方法:實例化對象(開闢內存空間)
__init__方法:對實例化對象進行初始化操作
__call__方法:讓類可調用,實現裝飾器
__str__方法:當使用print輸出對象的時候,默認打印對象的內存地址。如果類定義了__str__方法,那麼就會打印從在這個方法中return的數據
__del__方法:當刪除對象時,python解釋器會默認調用這個方法,讓這個對象的引用計數減1,當對象的引用計數爲0的時候,則對象纔會被真正刪除(內存被回收)。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章