Python 装饰器实战:从基础到类装饰器的完整指南
本文深入解析 Python 装饰器的多种用法,涵盖无参与有参装饰器的实现原理。重点演示如何利用 @wraps 保持函数元数据,以及如何通过判断参数类型实现带参与不带参装饰器的自适应调用。此外,还介绍了记录函数入参出参的高级技巧及类装饰器的编写方法,帮助开发者掌握 Python 高级特性。
Python 装饰器基础:无参与有参场景
首先介绍最简单的无参装饰器场景。当装饰器本身不需要接收任何额外参数时,调用方式最为直接,无需进行额外的函数调用操作。
def log1(func):
func()
@log1
def test():
print('test:')
接下来讨论带有参数的被装饰函数情况。此时装饰器需要能够接收并传递这些参数给原始函数,确保功能不被破坏。
def log2(func):
def inner(*args, **kwargs):
func(*args, **kwargs)
return inner
@log2
def test(num):
print('testlog2:',num,test.__name__)
test(20) #相当于log(test(20))
在使用装饰器时,一个常见的问题是原始函数的元数据(如名称)会被覆盖。通过引入 可以确保装饰器修饰后的函数保留原始的 name 属性值,这对于调试和日志记录至关重要。
不带参数的装饰器实现
不带参数的装饰器是最基础的形式,其核心逻辑是接收一个函数作为参数,并返回一个新的函数包装器。
def log3(func):
@wraps(func)
def inner(*args, **kwargs,):
func(*args, **kwargs)
return inner
@log3
def test(num):
print('testlog3:',num,test.__name__)
test(30) #相当于log(test(30))
带参数的装饰器设计
带参数的装饰器允许在装饰器定义时传入配置信息,这需要通过多层嵌套函数来实现,外层接收参数,内层接收函数。
def log4(level):
def log(func):
@wraps(func)
def inner(*args, **kwargs,):
if level == "warn":
print("%s is running" % func.__name__)
func(*args, **kwargs)
return inner
return log
@log4(level="warn")
def test(num):
print('testlog4:', num, test.__name__)
test(40)
自适应装饰器:兼容有参与无参调用
为了实现代码的通用性,可以设计一种自适应装饰器,使其既能像无参装饰器那样直接调用,也能像有参装饰器那样接收参数。这通常通过判断传入参数的类型来实现。
def log(arg):
if callable(arg): # 判断参入的参数是否是函数,不带参数的装饰器调用这个分支
def log3(func):
@wraps(func)
def inner(*args, **kwargs, ):
func(*args, **kwargs)
return inner
return log3
else:
def log4(func):
@wraps(func)
def inner(*args, **kwargs,):
if arg == "warn":
print("%s is running" % func.__name__)
func(*args, **kwargs)
return inner
return log4
@log(arg=None)
def test(num):
print('testlog:', num, test.__name__)
test(0)
记录入参出参的调试装饰器
除了控制流程,装饰器还可以用于记录函数的执行细节。例如,在函数执行前后打印入参和出参,有助于调试和分析函数行为。
def log5(func):
def inner(*args, **kwargs):
print('入参:',func.__name__, args, kwargs)
res =func(*args, **kwargs)
print('出参:',func.__name__, res)
return res
return inner
@log5
def test(num):
print('testlog5:', num, test.__name__)
return num
print(test(50))
类装饰器的实现与应用
除了函数形式的装饰器,Python 还支持类装饰器。通过实现 魔术方法,可以将类实例用作装饰器,提供更复杂的逻辑封装能力。
class Loging:
def __init__(self,level):
self.level = level
def __call__(self,func):
@wraps(func)
def inner(*args, **kwargs):
if self.level == "warn":
self.notify(func)
func(*args, **kwargs)
return inner
def notify(self,func):
print ("%s is running" % func.__name__)
@Loging(level="warn")
def test(num):
print('testLoging:', num, test.__name__)
test(0)
以上就是 Python 装饰器的核心使用示例与详细解析,涵盖了从基础到高级的应用场景。更多关于 Python 装饰器的深度资料,欢迎持续关注本站发布的其他技术文章。
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









