Python进阶: 通过实例详解装饰器(附代码)
Python中的装饰器有很多用处,比如输出日志、参数检查、代理设置、计数计时、结果缓存等等。本文就通过几个装饰器例子,详细解释一下Python中装饰器的用法。
- 一步步从简到繁学习装饰器用法
- 其他一些装饰器实例
- Python中自带的装饰器
按照惯例,先上代码:GitHub - xianhu/LearnPython: 以撸代码的形式学习Python
一步步从简到繁学习装饰器用法
(1)最简单的装饰器,实现日志输出功能:
# 构建装饰器
def logging(func):
@functools.wraps(func)
def decorator():
print("%s called" % func.__name__)
result = func()
print("%s end" % func.__name__)
return result
return decorator
# 使用装饰器
@logging
def test01():
return 1
# 测试用例
print(test01())
print(test01.__name__)
代码很简单,很容易看懂。这里注意"functools.wraps"用法,其目的是"test01.__name__"输出正确的"test01"。"@logging"相当于"test01 = logging(test01)",返回的是decorator函数,所以如果不加"functools.wraps",则"test01.__name__"返回为"decorator"。
注意,此时test01没有参数,对于带有参数的函数,logging装饰器则不再适用。那么如果想装饰带有参数的函数,装饰器该怎么写呢?
(2)装饰器传入函数参数,并正确返回结果:
# 构建装饰器
def logging(func):
@functools.wraps(func)
def decorator(a, b):
print("%s called" % func.__name__)
result = func(a, b)
print("%s end" % func.__name__)
return result
return decorator
# 使用装饰器
@logging
def test01(a, b):
print("in function test01, a=%s, b=%s" % (a, b))
return 1
# 测试用例
print(test01(1, 2))
这里的test01函数带有参数a、b,那么decorator函数带有同样的参数即可。那么问题又来了,如何让logging装饰器更加通用,而不是只装饰参数为两个的函数呢?这时候自然想到Python中的 * 和 ** 的用法。
# 构建装饰器
def logging(func):
@functools.wraps(func)
def decorator(*args, **kwargs):
print("%s called" % func.__name__)
result = func(*args, **kwargs)
print("%s end" % func.__name__)
return result
return decorator
# 使用装饰器
@logging
def test01(a, b):
print("in function test01, a=%s, b=%s" % (a, b))
return 1
# 使用装饰器
@logging
def test02(a, b, c=1):
print("in function test02, a=%s, b=%s, c=%s" % (a, b, c))
return 1
# 测试用例
print(test01(1, 2))
print(test02(1, 2, c=3, d