Python函数修饰符@的使用方法与原理详解
本文深入解析Python中函数修饰符@的使用机制。通过四个逐步递进的代码示例,详细演示如何定义修饰器、处理无参/有参函数,以及解决函数元数据丢失问题。重点讲解functools.wraps的作用及带参修饰器的实现逻辑,帮助开发者掌握Python装饰器的核心技巧。
Python修饰符@概述
Python中的函数修饰符@主要用于为现有函数添加额外功能,常见应用场景包括插入日志记录、性能测试以及事务处理等。
修饰器定义规则
定义一个有效的函数修饰符需遵循以下规则:
第一,修饰器本身必须是一个函数。
第二,该修饰器函数需接收被修饰的函数作为参数。
第三,修饰器必须返回一个新的函数对象。
第四,修饰器应尽可能维护被修饰函数的原始签名信息。
示例1展示了一个不带参数的被修饰函数的情况。
基础示例:无参函数修饰
def log(func):
def wrapper():
print('log开始 ...')
func()
print('log结束 ...')
return wrapper
@log
def test():
print('test ..')
test()
运行结果如下:
log开始 ...
test ..
log结束 ...
示例2演示了如何使用functools模块提供的wraps方法来修改函数属性。
属性修复:使用functools.wraps
def log(func):
def wrapper():
print('log开始 ...')
func()
print('log结束 ...')
return wrapper
@log
def test1():
print('test1 ..')
def test2():
print('test2 ..')
print(test1.__name__)
print(test2.__name__)
运行结果如下:
wrapper
test2
从结果可见,test1的函数名称发生了改变(变为wrapper),这可能导致依赖函数名的代码出现异常。为解决此问题,可以使用functools模块提供的wraps方法来修正函数属性。
from functools import wraps
def log(func):
@wraps(func)
def wrapper():
print('log开始 ...')
func()
print('log结束 ...')
return wrapper
@log
def test1():
print('test1 ..')
def test2():
print('test2 ..')
print(test1.__name__)
print(test2.__name__)
运行结果如下:
test1
test2
示例3展示了被修饰函数带有参数的情况。
进阶示例:处理带参函数
from functools import wraps
def log(func):
@wraps(func)
def wrapper(*args,**kwargs):
print('log开始 ...',func.__name__)
ret = func(*args,**kwargs)
print('log结束 ...')
return ret
return wrapper
@log
def test1(s):
print('test1 ..', s)
return s
@log
def test2(s1, s2):
print('test2 ..', s1, s2)
return s1 + s2
test1('a')
test2('a','bc')
运行结果如下:
log开始 ... test1
test1 .. a
log结束 ...
log开始 ... test2
test2 .. a bc
log结束 ...
示例4中,若修饰器本身也需要带参数,则需要在之前的基础上增加一层包装。
高级示例:带参修饰器
from functools import wraps
def log(arg):
def _log(func):
@wraps(func)
def wrapper(*args,**kwargs):
print('log开始 ...',func.__name__, arg)
ret = func(*args,**kwargs)
print('log结束 ...')
return ret
return wrapper
return _log
@log('module1')
def test1(s):
print('test1 ..', s)
return s
@log('module1')
def test2(s1, s2):
print('test2 ..', s1, s2)
return s1 + s2
test1('a')
test2('a','bc')
运行结果如下:
log开始 ... test1 module1
test1 .. a
log结束 ...
log开始 ... test2 module1
test2 .. a bc
log结束 ...
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













