Python 中的函数与装饰器

Posted on May 2, 2025

函数

  • 函数是一个对象
  • 在定义函数的时候,实际上是定义了一个变量,在编译的时候,函数体会被编译成一个 code object,保存到所定义的变量中
  • 可以和变量赋值操作进行类比

装饰器

  • 装饰器本质上是一个对象(可以是函数或者类),其接收一个对象(可以是函数或者类),然后返回一个新对象(可以是函数或者类)
  • 返回的新对象内部调用了被装饰的对象,这样可以不改变原对象内部的代码而改变其功能

用法

  • 最简用例

      def decorator(func):
          def wrapper(*args, **kwargs):
              # some logic ...
              out = func(*args, **kwargs)
              # some logic ...
              return out  #也可以是其他变量
          return wrapper
    
      @decorator
      def function(arg):
          #some logic ...
          return output
    
    • 加上装饰器的函数定义语句,相当于 function = decorator(function),它们编译时生成的字节码是一样的
    • 语句 function(arg) 等价于 decorator(func)(arg)
  • 装饰器本身接受其他参数

    • 此时的函数定义语句等价于 function = decorator(*args, **kwargs)(function)
    • 此时加上 @decorator(*args, **kwargs) 后,语句 function(arg) 等价于 decorator(*args, **kwargs)(function)(arg)
    • 相当于多加了一层嵌套函数
      def outer_decorator(*args, **kwargs)
          def inner_decorator(func):
              def wrapper(*args, **kwargs):
                  # some logic ...
                  out = func(*args, **kwargs)
                  # some logic ...
                  return out  #也可以是其他变量
              return wrapper
          return inner_decorator
    
      @outer_decorator(*args, **kwargs)
      def function(arg):
          #some logic ...
          return output
    
  • functools.wraps 装饰器

    • 用于装饰普通装饰器函数内部的 wrapper 函数
    • 一般情况下,使用装饰器时,被装饰函数的一些元数据会被覆盖。例如,装饰后的函数的 __name____doc__ 会变成装饰器内部函数的名称和文档字符串,而不是原始函数的
    • functools.wraps 装饰器在编写装饰器时保留被装饰函数的元数据(metadata)