程序员文章、书籍推荐和程序员创业信息与资源分享平台

网站首页 > 技术文章 正文

Python内置装饰器:深入理解其原理和应用

hfteth 2025-03-29 17:47:43 技术文章 9 ℃

装饰器(decorator)是Python中一种强大的编程技术,用于在不修改函数本身的情况下,为函数添加额外功能。内置装饰器是Python提供的一些常用的装饰器,可以简化代码并提高开发效率。

内置装饰器类型

Python内置装饰器主要有以下几种类型:

  • 通用装饰器(@wraps):用于保留被装饰函数的原始属性,例如名称、文档字符串等。
  • 函数属性装饰器(@property、@staticmethod、@classmethod):用于改变函数的行为或属性。
  • 异常处理装饰器(@tryexcept、@finally):用于简化异常处理代码。
  • 其他装饰器(@lru_cache、@functools.wraps):用于实现其他功能,例如缓存函数结果或增强函数功能。

通用装饰器(@wraps)

@wraps装饰器用于保留被装饰函数的原始属性。当使用其他装饰器装饰函数时,被装饰函数的名称、文档字符串等属性可能会丢失。@wraps装饰器可以解决这个问题,确保被装饰函数的属性不被修改。

def my_function(x, y):
  """My function description."""
  return x + y

@wraps(my_function)
def decorated_function(x, y):
  return my_function(x, y)

print(decorated_function.__name__)  # 输出:my_function
print(decorated_function.__doc__)  # 输出:My function description.

函数属性装饰器

Python提供了三个函数属性装饰器:@property、@staticmethod和@classmethod。

  • @property装饰器:将函数转换为属性,可以通过点号语法访问。
class Person:
  def __init__(self, name, age):
    self.name = name
    self._age = age

  @property
  def age(self):
    return self._age

  @age.setter
  def age(self, value):
    if value < 0:
      raise ValueError("Age cannot be negative")
    self._age = value

person = Person("Alice", 30)
print(person.age)  # 输出:30

person.age = 25
print(person.age)  # 输出:25
  • @staticmethod装饰器:将函数转换为静态方法,无需创建实例即可调用。
  • class Math:
      @staticmethod
      def add(x, y):
        return x + y
    
    print(Math.add(1, 2))  # 输出:3
    


  • @classmethod装饰器:将函数转换为类方法,可以使用类名作为第一个参数调用。

  • class Person:
      def __init__(self, name, age):
        self.name = name
        self.age = age
    
      @classmethod
      def from_birth_year(cls, name, birth_year):
        age = 2024 - birth_year
        return cls(name, age)
    
    person = Person.from_birth_year("Bob", 1990)
    print(person.name)  # 输出:Bob
    print(person.age)  # 输出:34
    

    异常处理装饰器

    Python提供了两个异常处理装饰器:@tryexcept和@finally。

    • @tryexcept装饰器:用于简化try-except异常处理代码。
    def divide(x, y):
      try:
        return x / y
      except ZeroDivisionError:
        return "Cannot divide by zero"
    
    @tryexcept(ZeroDivisionError):
    def safe_divide(x, y):
      return x / y
    
    print(safe_divide(10, 2))  # 输出:5.0
    print(safe_divide(10, 0))  # 输出:Cannot divide by zero
    


    • @finally装饰器:用于确保在任何情况下都会执行的代码块。
    def open_file(filename):
      try:
        f = open(filename)
        # 使用文件
      finally:
        f.close()
    
    with open_file("myfile.txt") as f:
      # 使用文件
    


    Tags:

    最近发表
    标签列表