首頁 > 軟體

一起來看看python的裝飾器程式碼

2022-03-24 19:00:57

裝飾器通用模型

def wrapper(fn):
    def inner(*args, **kwargs):
        ret = fn(*args, **kwargs)
        return ret
    return inner

裝飾器幾個關鍵點

"""
1.函數可以當引數傳遞
2.函數可以作為返回值進行返回
3.函數名稱可以當成變數一樣進行賦值操作
裝飾器本質上是個閉包
在不改變原有函數呼叫的情況下,給函數增加新的功能
"""

舉個例子

#!/usr/bin/python
def admin(game):
    def inner(*args, **kwargs):  # inner新增了引數,args 一定是個元組 kwargs 一定是字典
        print('開啟Wg')
        result = game(*args, **kwargs)  # * ** 表示把args元組和kwargs打散成位置引數,關鍵字引數傳遞進去
        print('關閉Wg')
        return result
    return inner
@admin
def play_dnf(username, password):
    print(f'開始玩DNF,賬號:{username},密碼:{password}')
    print('刀斬肉身,心斬靈魂')
    return '掉落:戮蠱的哀鳴炮'
@admin
def play_wow(race, occupation, server_name, camp):
    print(f'開始玩魔獸世界,種族:{race},職業:{occupation},伺服器:{server_name},陣營:{camp}')
    print('為了辛多雷的榮耀')
    return '掉落:灰燼使者'
if __name__ == '__main__':
    ret1 = play_dnf('大馬猴', '888888')
    print(ret1)
    ret2 = play_wow('血精靈', '聖騎士', '迴音山', '部落')
    print(ret2)

這程式碼還是很好懂的,我就不解釋了,然後是執行結果

python demo.py
開啟Wg
開始玩DNF,賬號:大馬猴,密碼:888888
刀斬肉身,心斬靈魂
關閉Wg
掉落:戮蠱的哀鳴炮
開啟Wg
開始玩魔獸世界,種族:血精靈,職業:聖騎士,伺服器:迴音山,陣營:部落
為了辛多雷的榮耀
關閉Wg
掉落:灰燼使者
Process finished with exit code 0

一個函數被多個裝飾器裝飾,又將如何執行呢?

#!/usr/bin/python
def wrapper1(fn):
    def inner(*args, **kwargs):
        print('這是w1進入')
        ret = fn(*args, **kwargs)
        print('這是w1出去')
        return ret
    return inner
def wrapper2(fn):
    def inner(*args, **kwargs):
        print('這是w2進入')
        ret = fn(*args, **kwargs)
        print('這是w2出去')
        return ret
    return inner
@wrapper1
@wrapper2
def target():
    print('我是目標')
if __name__ == '__main__':
    target()

直接給出執行順序

一個函數被多個裝飾器裝飾的執行順序

# w1 w2 target w2 w1

帶引數的裝飾器

裝飾器的語法允許我們在呼叫時,提供其它引數,比如@decorator(a)。這樣,就為裝飾器的編寫和使用提供了更大的靈活性。
(在上面又套了一層函數)

比如,我們可以在裝飾器中指定紀錄檔的等級,因為不同業務函數可能需要的紀錄檔級別是不一樣的。

def use_logging(level):
    def decorator(func):
        def wrapper(*args, **kwargs):
            if level == "warn":
                logging.warn("%s is running" % func.__name__)
            elif level == "info":
                logging.info("%s is running" % func.__name__)
            return func(*args)
        return wrapper
    return decorator
@use_logging(level="warn")
def foo(name='foo'):
    print("i am %s" % name)
foo()

類裝飾器

沒錯,裝飾器不僅可以是函數,還可以是類,相比函數裝飾器,類裝飾器具有靈活度大、高內聚、封裝性等優點。使用類裝飾器主要依靠類的__call__方法,當使用 @ 形式將裝飾器附加到函數上時,就會呼叫此方法。

class Foo(object):
    def __init__(self, func):
        self._func = func
    def __call__(self):
        print ('class decorator runing')
        self._func()
        print ('class decorator ending')
@Foo
def bar():
    print ('bar')
bar()

總結

本篇文章就到這裡了,希望能夠給你帶來幫助,也希望您能夠多多關注it145.com的更多內容!    


IT145.com E-mail:sddin#qq.com