1. 程式人生 > >Python 裝飾器@,對函式進行功能擴充套件,開閉原則

Python 裝飾器@,對函式進行功能擴充套件,開閉原則

裝飾器可以對原函式進行功能擴充套件,但還不需要修改原函式的內容(開閉原則),也不需要修改原函式的呼叫。

 

demo.py(裝飾器,@):

# 閉包
def w1(func):
    def inner():
        # 對原函式進行功能擴充套件
        print("功能擴充套件")
        func()
        # return func()  # 如果原函式需要返回值,可以return
    return inner  # 閉包

@w1
# 相當於 f1 = w1(f1)
def f1():
    print('f1')  # 原函式不需要修改


f1()  # 原函式的呼叫也不需要修改

demo.py(裝飾器通用格式,對不定長引數並且有返回值的函式進行裝飾):


def set_func(func):
    def call_func(*args, **kwargs):
        print("裝飾器擴充套件的功能")
        return func(*args, **kwargs)  # 這裡的*和*表示拆包。 不管有沒有返回值,return都沒問題。
    return call_func


@set_func  # 相當於 test1 = set_func(test1)
# 對含有不定長引數並且有返回值的函式進行裝飾。
def test1(num, *args, **kwargs):
    print("-----test1----%d" % num)
    return "ok"


ret = test1(100)
print(ret)

demo.py(多個裝飾器的裝飾順序):


def add_1(func):
    def call_func(*args, **kwargs):
        print("裝飾器1 擴充套件的功能")
        return func(*args, **kwargs)
    return call_func

def add_2(func):
    def call_func(*args, **kwargs):
        print("裝飾器2 擴充套件的功能")
        return func(*args, **kwargs)
    return call_func


@add_2
@add_1
# 先裝飾add_1,再裝飾add_2
def test1():
    print("------test1------")


test1()  # 在呼叫函式之前就已經裝飾好了。

# 裝飾器2 擴充套件的功能
# 裝飾器1 擴充套件的功能
# ------test1------

demo.py(用類充當裝飾器):


# 用類充當裝飾器
class Test(object):
    def __init__(self, func):
        self.func = func

    def __call__(self, *args, **kwargs):
        print("這裡是裝飾器新增的功能.....")
        return self.func(*args, **kwargs)


@Test  # 相當於get_str = Test(get_str)  # 例項化物件,呼叫__init__方法。
def get_str():
    return "haha"

print(get_str())   # 例項物件(),會自動呼叫物件的__call__方法。