Python装饰器类似于Java中的切面,以类似Java注解的形式,将一个函数替换为另一个函数
def log(func):
from datetime import datetime
return lambda *args, **kwargs: [
print(
f"[{datetime.now()}] >>> {func.__name__}"
f"({', '.join([', '.join(args), ', '.join([f'{k}={v}' for k, v in kwargs.items()])])})"),
func(*args, **kwargs),
print(
f"[{datetime.now()}] <<< {func.__name__}"
f"({', '.join([', '.join(args), ', '.join([f'{k}={v}' for k, v in kwargs.items()])])})"),
][1]
@log
def hello(name, **kwargs):
print(f"Hello: {', '.join([name] + list(kwargs.values()))}")
return "OK"
result = hello("world", alpha="ALPHA", beta="BETA")
print("Result:", result)
[2019-03-17 16:38:35.629506] >>> hello(world, alpha=ALPHA, beta=BETA)
Hello: world, ALPHA, BETA
[2019-03-17 16:38:35.629561] <<< hello(world, alpha=ALPHA, beta=BETA)
Result: OK
def log(level):
from datetime import datetime
return lambda func: lambda *args, **kwargs: [
print(
f"[{datetime.now()}] {level} >>> {func.__name__}"
f"({', '.join([', '.join(args), ', '.join([f'{k}={v}' for k, v in kwargs.items()])])})"),
func(*args, **kwargs),
print(
f"[{datetime.now()}] {level} <<< {func.__name__}"
f"({', '.join([', '.join(args), ', '.join([f'{k}={v}' for k, v in kwargs.items()])])})"),
][1]
@log("DEBUG")
def hello(name, **kwargs):
print(f"Hello: {', '.join([name] + list(kwargs.values()))}")
return "OK"
result = hello("world", alpha="ALPHA", beta="BETA")
print("Result:", result)
[2019-03-17 17:09:31.427342] DEBUG >>> hello(world, alpha=ALPHA, beta=BETA)
Hello: world, ALPHA, BETA
[2019-03-17 17:09:31.427401] DEBUG <<< hello(world, alpha=ALPHA, beta=BETA)
Result: OK
class Log(object):
def __init__(self, level):
self.level = level
def __call__(self, func):
from datetime import datetime
level = self.level
return lambda *args, **kwargs: [
print(
f"[{datetime.now()}] {level} >>> {func.__name__}"
f"({', '.join([', '.join(args), ', '.join([f'{k}={v}' for k, v in kwargs.items()])])})"),
func(*args, **kwargs),
print(
f"[{datetime.now()}] {level} <<< {func.__name__}"
f"({', '.join([', '.join(args), ', '.join([f'{k}={v}' for k, v in kwargs.items()])])})"),
][1]
@Log("DEBUG")
def hello(name, **kwargs):
print(f"Hello: {', '.join([name] + list(kwargs.values()))}")
return "OK"
result = hello("world", alpha="ALPHA", beta="BETA")
print("Result:", result)
[2019-03-17 17:23:17.428339] DEBUG >>> hello(world, alpha=ALPHA, beta=BETA)
Hello: world, ALPHA, BETA
[2019-03-17 17:23:17.428404] DEBUG <<< hello(world, alpha=ALPHA, beta=BETA)
Result: OK
装饰器会替换原函数,导致原函数的元信息被替换。使用@wraps装饰器,可以还原函数的元数据
class Log(object):
def __init__(self, level):
self.level = level
def __call__(self, func):
from datetime import datetime
from functools import wraps
level = self.level
return wraps(func)(lambda *args, **kwargs: [
print(
f"[{datetime.now()}] {level} >>> {func.__name__}"
f"({', '.join([', '.join(args), ', '.join([f'{k}={v}' for k, v in kwargs.items()])])})"),
func(*args, **kwargs),
print(
f"[{datetime.now()}] {level} <<< {func.__name__}"
f"({', '.join([', '.join(args), ', '.join([f'{k}={v}' for k, v in kwargs.items()])])})"),
][1])
@Log("DEBUG")
@Log("DEBUG")
@Log("DEBUG")
def hello(name, **kwargs):
print(f"Hello: {', '.join([name] + list(kwargs.values()))}")
return "OK"
result = hello("world", alpha="ALPHA", beta="BETA")
print("Result:", result)
[2019-03-17 17:30:54.099987] DEBUG >>> hello(world, alpha=ALPHA, beta=BETA)
[2019-03-17 17:30:54.100037] DEBUG >>> hello(world, alpha=ALPHA, beta=BETA)
[2019-03-17 17:30:54.100050] DEBUG >>> hello(world, alpha=ALPHA, beta=BETA)
Hello: world, ALPHA, BETA
[2019-03-17 17:30:54.100068] DEBUG <<< hello(world, alpha=ALPHA, beta=BETA)
[2019-03-17 17:30:54.100079] DEBUG <<< hello(world, alpha=ALPHA, beta=BETA)
[2019-03-17 17:30:54.100089] DEBUG <<< hello(world, alpha=ALPHA, beta=BETA)
Result: OK