1. 程式人生 > >Learn Python—函數(裝飾器)

Learn Python—函數(裝飾器)

結果 註釋 return rom 添加 body urn 簡單 裝飾器

裝飾器

開放封閉原則

開放:對函數的擴展是開放的

封閉:對函數的修改是封閉的

裝飾器的作用

在不更改原函數調用方式的前提下,對原函數添加新功能

# ①引子——為什麽要有裝飾器
為了在不修改原函數的基礎上為函數添加新功能,產生了裝飾器

# ②簡單裝飾器
def deco(f):
    def wrapper():
        """原函數前添加的功能"""
        f()
        """原函數後添加的功能"""
    return wrapper

def func():
    print(這是原函數!)

func = deco(func)
func()

#
③裝飾器的語法糖 def deco(f): def wrapper(): """原函數前添加的功能""" f() """原函數後添加的功能""" return wrapper @deco # ——>此處效果等同於 func = deco(func) def func(): print(這是原函數) func() # ④帶返回值的裝飾器 def deco(f): def wrapper(): """原函數前添加的功能""" res = f() """原函數後添加的功能
""" return res return wrapper @deco def func(): print(這是原函數) func() # ⑤帶參數、帶返回值的裝飾器 def deco(f): def wrapper(*args,**kwargs): """原函數前添加的功能""" res = f(*args,**kwargs) """原函數後添加的功能""" return res return wrapper @deco def func(*args,**kwargs):
print(這是原函數) func(*args,**kwargs) # ⑥多層裝飾器 # todo # ⑦多個裝飾器修飾同一個函數 # todo

裝飾器的固定格式

def deco(f):
    def wrapper(*args,**kwargs):
    """原函數前添加的功能"""
    res = f(*args,**kwargs)
    """原函數後添加的功能"""
    return res
    return wrapper

@deco
def func(*args,**kwargs):
    pring(這是原函數)

func(*args,**kwargs)

裝飾器的固定格式—wraps版

如果想使用原函數的雙下方法,則需要再調用系統裝飾器@ wraps(func)

from functools import wraps

def deco(func):
    @wraps(func) #加在最內層函數正上方
    def wrapper(*args,**kwargs):
        return func(*args,**kwargs)
    return wrapper

@deco
def origin_func():
    ‘‘‘
    這是原函數的註釋
    :return:
    ‘‘‘
    print(這是原函數)

# 雖然已經執行了裝飾器,origin_func已經指向wrapper,但是如果用了@wraps(func)裝飾器之後調用origin_func的雙下方法依然是原函數origin_func的
print(origin_func.__name__)
>>> origin_func

print(origin_func.__doc__)
>>> 這是原函數的註釋
>>> :return:

帶參數的裝飾器

def outer(flag):
    def timer(func):
        def inner(*args,**kwargs):
            if flag:
                print(‘‘‘執行函數之前要做的‘‘‘)
            re = func(*args,**kwargs)
            if flag:
                print(‘‘‘執行函數之後要做的‘‘‘)
            return re
        return inner
    return timer

# 此處先執行函數調用outer(False) —> 返回timer —>@timer —>func = timer(func) —> func = inner
@outer(False) 
def func():
    print(111)

func()

多個裝飾器裝飾同一個函數

def wrapper1(func):
    def inner1():
        print(wrapper1 ,before func)
        func()
        print(wrapper1 ,after func)
    return inner1

def wrapper2(func):
    def inner2():
        print(wrapper2 ,before func)
        func()
        print(wrapper2 ,after func)
    return inner2

@wrapper2 # 將inner1進行裝飾,即inner1 = wrapper2(inner1) = inner2
@wrapper1 # 先執行這個裝飾器,即f = wrapper1(f) = inner1
def f():
    print(in f)

f()

# 結果
>>> wrapper2 ,before func
>>> wrapper1 ,before func
>>> in f
>>> wrapper1 ,after func
>>> wrapper2 ,after func

Learn Python—函數(裝飾器)