什麼是Python裝飾器？

• 計算函數運行時間
• 給函數打日誌
• 類型檢查

4.簡單示例

``````from time import time, sleep

def fun_one():
start = time()
sleep(1)
end = time()
cost_time = end - start
print("func one run time {}".format(cost_time))

def fun_two():
start = time()
sleep(1)
end = time()
cost_time = end - start
print("func two run time {}".format(cost_time))

def fun_three():
start = time()
sleep(1)
end = time()
cost_time = end - start
print("func three run time {}".format(cost_time))
``````

``````def run_time(func):
def wrapper():
start = time()
func()                  # 函數在這裏運行
end = time()
cost_time = end - start
print("func three run time {}".format(cost_time))
return wrapper

@run_time
def fun_one():
sleep(1)

@run_time
def fun_two():
sleep(1)

@run_time
def fun_three():
sleep(1)
``````

5.帶參數的裝飾器

``````func three run time 1.0003271102905273
func three run time 1.0006263256072998
func three run time 1.000312328338623
``````

``````def logger(msg=None):
def run_time(func):
def wrapper(*args, **kwargs):
start = time()
func()                  # 函數在這裏運行
end = time()
cost_time = end - start
print("[{}] func three run time {}".format(msg, cost_time))
return wrapper
return run_time

@logger(msg="One")
def fun_one():
sleep(1)

@logger(msg="Two")
def fun_two():
sleep(1)

@logger(msg="Three")
def fun_three():
sleep(1)

fun_one()
fun_two()
fun_three()
``````

``````[One] func three run time 1.0013229846954346
[Two] func three run time 1.000720500946045
[Three] func three run time 1.0001459121704102
``````

6.自定義屬性的裝飾器

``````def logger_info(func):
logmsg = func.__name__
def wrapper():
func()
log.log(logging.INFO, "{} if over.".format(logmsg))
return wrapper
``````

http://logging.INFO是打印日誌的等級，如果我們僅僅寫一個基本的日誌裝飾器logger_info，那麼它的靈活度太差了，因爲如果我們要輸出DEBUG、WARING等級的日誌，還需要重新寫一個裝飾器。

• 利用前面所講的帶參數裝飾器，把日誌等級傳入裝飾器
• 利用自定義屬性來修改日誌等級

``````import logging
from functools import partial

def wrapper_property(obj, func=None):
if func is None:
return partial(attach_wrapper, obj)
setattr(obj, func.__name__, func)
return func

def logger_info(level, name=None, message=None):
def decorate(func):

logmsg = message if message else func.__name__

def wrapper(*args, **kwargs):
log.log(level, logmsg)
return func(*args, **kwargs)

@wrapper_property(wrapper)
def set_level(newlevel):
nonlocal level
level = newlevel

@wrapper_property(wrapper)
def set_message(newmsg):
nonlocal logmsg
logmsg = newmsg

return wrapper

return decorate

@logger_info(logging.WARNING)
def main(x, y):
return x + y
``````

``````main(3, 3)

# 輸出
# WARNING:Test:main
# 6
``````

``````main.set_level(logging.ERROR)
main(5, 5)

# 輸出
# ERROR:Test:main
# 10
``````

7.保留元信息的裝飾器

``````from time import time

def run_time(func):
def wrapper(*args, **kwargs):
start = time()
func()                  # 函數在這裏運行
end = time()
cost_time = end - start
print("func three run time {}".format(cost_time))
return wrapper

#學習中遇到問題沒人解答？小編創建了一個Python學習交流羣：711312441
@run_time
def fun_one():
'''
func one doc.
'''
sleep(1)

fun_one()

print(fun_one.__name__)
print(fun_one.__doc__)

# 輸出
# wrapper
# None
``````

``````from time import time
from functools import wraps

def run_time(func):
@wraps(func)                                # <- 這裏加 wraps(func) 即可
def wrapper(*args, **kwargs):
start = time()
func()                  # 函數在這裏運行
end = time()
cost_time = end - start
print("func three run time {}".format(cost_time))
return wrapper

@run_time
def fun_one():
'''
func one doc.
'''
sleep(1)

fun_one()

print(fun_one.__name__)
print(fun_one.__doc__)

# 輸出
# fun_one
# func one doc.
``````