Python装饰器
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)))