理解Python類裝飾器__call__

  • 背景

    裝飾器模式是我經常使用的一種Python設計模式,也非常的好用,一般是用函數實現,但是這種實現有一個缺點。

    如果邏輯非常的複雜,寫在一個函數中,會讓函數非常長且冗餘,需要把小功能的抽象,然後再進行組合 而類裝飾器,就適用於這種場景。

# coding=utf-8
# 深入理解類裝飾器


# 一:類裝飾器(都不帶參數)
class ClsDeco:
    def __init__(self, func):
        self.func = func

    def __call__(self, *args, **kwargs):
        print(f'Running {self.func.__name__}')
        self.func()
        print('End')

@ClsDeco  # 等價於 bar = ClsDeco(bar)
def bar():
    print('do something')

# call bar()
# OUT:
#     Running bar
#     do something
#     End









# 二:類裝飾器帶參數
class ClsDeco1:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __call__(self, func, *args, **kwargs):
        print(f'Running {func.__name__}')
        print(f'Using x + y = {self.x + self.y}')
        return func


@ClsDeco1(1,2) # 等價於 bar1 = ClsDeco1(1,2)(bar1)
def bar1():
    print('do something')


# call bar1()
# OUT:
#     Running bar1
#     Using x + y = 3
#     do something









# 三:類裝飾器不帶參數,被包裝對象帶參數
class ClsDeco2:
    def __init__(self, func):
        self.func = func

    def __call__(self, *args, **kwargs):
        print(f'Running {self.func.__name__}')
        self.func(*args, **kwargs)
        print('End')

@ClsDeco2  # 等價於bar2 = ClsDeco2(bar2)
def bar2(a,b):
    print('do something')
    print(f'return a + b = {a + b}')


# bar2(1,2)
# OUT:
#     Running bar2
#     do something
#     return a + b = 3
#     End









# 四:類裝飾器帶參數且被裝飾對象也帶參數
class ClsDeco3:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __call__(self, func, *args, **kwargs):
        print(f'Using x + y = {self.x + self.y}')

        def wrapper(*args, **kwargs):
            func(*args, **kwargs)
            print('Ending')

        return wrapper



@ClsDeco3(1, 2) # 等價於 bar3 = ClsDeco3(1, 2)(bar3)
def bar3(a, b):
    print('do something')
    print(f'return a + b = {a + b}')


# call bar3(1,2)
# OUT:
#     Using x + y = 3
#     do something
#     return a + b = 3
#     Ending





if __name__ == '__main__':
    bar3(1,2)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章