1. 简单装饰器
import time
def timer(func):
def wrapper(*args,**kwargs):
t1 = time.time()
func(*args,**kwargs)
t2 = time.time()
run_time = t2 - t1
print(run_time)
return wrapper
@timer
def foo():
time.sleep(3)
#
foo() # 3.0006301403045654
foo = timer(foo) # 等同于使用timer装饰器
foo() # 3.0006301403045654
2. 带参数的装饰器
import logging
def log(level):
def decorator(func):
def wrapper(*args,**kwargs):
if level == 'warn':
logging.warn("%s is running" % func.__name__)
return func(*args,**kwargs)
return wrapper
return decorator
@log('warn')
def foo(a='123'):
print('the number is %s' %a)
foo()
the number is 123
WARNING:root:foo is running
3. 类装饰器
import logging
def log(level):
def decorator(func):
def wrapper(*args,**kwargs):
if level == 'warn':
logging.warn("%s is running" % func.__name__)
return func(*args,**kwargs)
return wrapper
return decorator
@log('warn')
def foo(a='123'):
print('the number is %s' %a)
foo()
the number is 123
WARNING:root:foo is running
4. 类装饰器
import logging
def log(level):
def decorator(func):
def wrapper(*args,**kwargs):
if level == 'warn':
logging.warn("%s is running" % func.__name__)
return func(*args,**kwargs)
return wrapper
return decorator
@log('warn')
def foo(a='123'):
print('the number is %s' %a)
foo()
the number is 123
WARNING:root:foo is running
5. functools.wraps
#装饰器有个缺点,会改变原函数的元信息
#functools.wraps本身也是装饰器,可把元信息拷贝到装饰器函数中,使元信息和原装饰器一致
from functools import wraps
def logged(func):
@wraps(func)
def with_logging(*args,**kwargs):
print(func.__name__ + "was called")
return func(*args,**kwargs)
return with_logging
@logged
def f(x):
"""does soma math"""
return x + x * x
print(f.__name__)
print(f.__doc__)
6. 装饰器顺序
@a
@b
@c
def f():
pass
# 等价于
f = a(b(c(f)))