Python函数修饰符@的使用方法与原理详解

拾光
拾光
发布时间:2026-10-13 | 6人浏览过
原创

本文深入解析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结束 ...

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表