python裝飾器

由於沒有真正實用經驗,所以只記錄基本用法,以免經常不用忘的太徹底。

 

簡單說,decorator也是一個函數,可以在不更改另一個函數的情況下,改變或增加另一個函數的功能。

1,不使用裝飾器。

 

def decoTest(func):
    print("before")
    func()
    print("after")

def test():
    print('Hello, World')

decoTest(test)

   爲了達到在test()執行前後分別執行不同語句功能,將test作爲參數,傳入decoTest中。之後需要調用decoTest函數,如果想直接調用test來達到這個目的,需要使用裝飾器。

 

 

2,使用@語法

 

def decoTest(func):
    print("before")
    func()
    print("after")
    return func

@decoTest
def test():
    print('Hello, World')


test

   在decoTest中增加了返回值,返回傳入的函數。相當於執行了decoTest(test)。所以結果與上面的相同。所以如果最後調用的是test(),將多輸出一個Hello, World。

 

 

3,爲解決2中調用test()多輸出一個Hello, World。對decoTest進行包裝,使它返回一個函數。

 

def decoTest(func):
    def wrapper():
        print('before')
        func()
        print('after')
    return wrapper

@decoTest
def test():
    print('Hello, World')


test()

   此時的輸出不會再多一行。因爲返回的是函數,執行test()相當是將test傳入decoTest中,decoTest返回wrapper,此時因爲執行的是test(),所以最終會執行wrapper()。

 

 

4,解決帶參數函數的裝飾。

 

def decoTest(func):
    def wrapper(a, b):
        print('before')
        func(a, b)
        print('after')
    return wrapper

@decoTest
def test(a, b):
    print('a + b =', a + b)


test(2, 9)

    結果爲:

before
a + b = 11
after

    因爲裝飾器函數返回的是一個函數,所以可以接受參數。所以2,9也傳入了wrapper中,所以返回正確。

 

 

5,使用*, **來解決參數數量的不確定性。

 

def decoTest(func):
    def wrapper(*args, **kwargs):
        print('before')
        func(*args, **kwargs)
        print('after')
    return wrapper

@decoTest
def test(a, b, c, d):
    print('sum =', a + b + c + d)

@decoTest
def test2(*args, **kwargs):
    print("%s, %s" % (args, kwargs))

test(2, 9, 10, 23)

test2(2, 3, 5, a = 5, c = 2)

   test和test2都實現了在本身函數之前之後分別輸出某個語句。

 

 

6,裝飾器函數也可以傳入參數。

 

def deco(arg) :
    def decoTest(func):
        def wrapper(*args, **kwargs):
            print('before', arg)
            func(*args, **kwargs)
            print('after', arg)
        return wrapper
    return decoTest


@deco("test")
def test(a, b, c, d):
    print('sum =', a + b + c + d)

@deco("test2")
def test2(*args, **kwargs):
    print("%s, %s" % (args, kwargs))

test(2, 9, 10, 23)

test2(2, 3, 5, a = 5, c = 2)

    輸出結果爲:

before test
sum = 44
after test
before test2
(2, 3, 5), {'c': 2, 'a': 5}
after test2

   裝飾器函數裏面嵌套定義了兩個函數。例子中裝飾器函數爲deco,deco返回的是函數decoTest,decoTest有一個函數參數,裝飾器返回的函數可以接受另一個函數,而decoTest又返回了wrapper函數。所以decoTest函數可以接受多個參數並最終輸出。

 

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