Python装饰器之类装饰器详解

Written by

in

文章目录
  • 在Python中,装饰器是一种允许我们在不改变原有代码的情况下,动态地增加或修改函数和类功能的工具。 类装饰器相较于函数装饰器,功能更为强大和灵活,因为它们不仅可以修饰类的方法,还可以修饰类本身。
  • 装饰器是一个接受函数或类并返回一个新函数或新类的高阶函数。它们通常通过 @ 符号来使用。 在使用装饰器时,我们将装饰器放在被装饰对象的上方,这样装饰器就会在对象创建时自动应用。
  • 类装饰器在实际开发中有很多应用场景,下面是几个常见的例子:
  • 接下来,我们将通过一个综合示例来展示如何使用类装饰器。 这个示例将包含一个日志记录装饰器、一个权限检查装饰器和一个数据验证装饰器。 import datetime def log_activity(cls): class WrappedClass(cls): def __getattribute__(self, name): attr = super().__getattribute__(name) if callable(attr): def logged(*args, **kwargs): print(f”Calling {name} with arguments {args} and {kwargs} at {datetime.datetime.now()}”) result = attr(*args, **kwargs) print(f”{name} returned {result}”) return result return logged return attr return WrappedClass def require_permission(permission): def decorator(cls): class WrappedClass(cls): def __getattribute__(self, name): attr = super().__getattribute__(name) if callable(attr): def secured(*args, **kwargs): if not self.has_permission(permission): raise PermissionError(f”Permission {permission} required”) return attr(*args, **kwargs) return secured return attr return WrappedClass return decorator def validate_params(cls): class WrappedClass(cls): def method_with_validation(self, x): if not isinstance(x, int): raise ValueError(“Parameter x must be an integer”) return super().method_with_validation(x) return WrappedClass @log_activity @require_permission(“admin”) @validate_params class MyClass: def __init__(self, is_admin): self.is_admin = is_admin def has_permission(self, permission): return self.is_admin def method_with_validation(self, x): return f”Received {x}” # 测试综合示例 admin_obj = MyClass(is_admin=True) print(admin_obj.method_with_validation(10)) # 正常调用 try: admin_obj.method_with_validation(“a”) # 抛出 ValueError except ValueError as e: print(e) user_obj = MyClass(is_admin=False) try: user_obj.method_with_validation(10) # 抛出 PermissionError except PermissionError as e: print(e)
  • 类装饰器是 Python 中一个非常强大的工具,可以用来扩展和修改类的行为。通过类装饰器,我们可以在不修改原始代码的情况下为类添加额外的功能。 在实际开发中,类装饰器有很多应用场景,包括日志记录、访问控制、数据验证等。 以上为个人经验,希望能给大家一个参考,也希望大家多多支持风君子博客。 您可能感兴趣的文章: python 自定义装饰器使用及原理详解(最新推荐) Python中的装饰器链(decorator chain)详解 python 装饰器带参数和不带参数步骤详解 详解Python如何利用装饰器实现重试机制 Python中装饰器和魔法方法的区别解析
  • 目录
    • 1. 引言
    • 2. 装饰器的基本概念
      • 2.1. 函数装饰器复习
      • 2.2 类装饰器的定义和使用
    • 3. 类装饰器的应用场景
      • 3.1. 自动添加属性
      • 3.2 访问控制
      • 3.3 数据验证
    • 4. 综合示例
      • 4.1 输出结果
      • 4.2 解释
    • 总结

      在Python中,装饰器是一种允许我们在不改变原有代码的情况下,动态地增加或修改函数和类功能的工具。

      类装饰器相较于函数装饰器,功能更为强大和灵活,因为它们不仅可以修饰类的方法,还可以修饰类本身。

      装饰器是一个接受函数或类并返回一个新函数或新类的高阶函数。它们通常通过 @ 符号来使用。

      在使用装饰器时,我们将装饰器放在被装饰对象的上方,这样装饰器就会在对象创建时自动应用。

      在介绍类装饰器之前,我们先简单回顾一下函数装饰器的基本用法。

      def my_decorator(func):
          def wrapper(*args, **kwargs):
              print("Something is happening before the function is called.")
              result = func(*args, **kwargs)
              print("Something is happening after the function is called.")
              return result
          return wrapper
      
      @my_decorator
      def say_hello(name):
          print(f"Hello, {name}!")
      
      say_hello("Alice")

      运行上述代码,输出结果为:

      Something is happening before the function is called.
      Hello, Alice!
      Something is happening after the function is called.

      类装饰器与函数装饰器类似,只不过它们接受一个类作为参数,并返回一个新类。

      最简单的类装饰器可以这样定义:

      def class_decorator(cls):
          class WrappedClass(cls):
              def new_method(self):
                  print("This is a new method added by the decorator.")
              def existing_method(self):
                  print("This method is overridden by the decorator.")
          return WrappedClass
      
      @class_decorator
      class MyClass:
          def existing_method(self):
              print("This method exists in the original class.")
      
      obj = MyClass()
      obj.new_method()          # 调用新增的方法
      obj.existing_method()     # 调用被重写的方法

      运行上述代码,输出结果为:

      This is a new method added by the decorator.
      This method is overridden by the decorator.

      在这个例子中,class_decorator 是一个类装饰器,它接受一个类 MyClass 作为参数,并返回一个新的类 WrappedClassWrappedClass 继承自 MyClass,并新增和重写了一些方法。

      类装饰器在实际开发中有很多应用场景,下面是几个常见的例子:

      类装饰器可以用来自动为类添加一些属性。

      例如,我们可以创建一个装饰器,自动为类添加一个 created_at 属性,记录对象的创建时间。

      import datetime
      
      def add_timestamp(cls):
          class WrappedClass(cls):
              def __init__(self, *args, **kwargs):
                  super().__init__(*args, **kwargs)
                  self.created_at = datetime.datetime.now()
          return WrappedClass
      
      @add_timestamp
      class MyClass:
          def __init__(self, name):
              self.name = name
      
      obj = MyClass("Alice")
      print(obj.name)        # 输出: Alice
      print(obj.created_at)  # 输出: 对象的创建时间

      类装饰器可以用来控制类的方法访问权限。

      例如,我们可以创建一个装饰器,要求调用某些方法时必须有管理员权限。

      def require_admin(cls):
          class WrappedClass(cls):
              def admin_method(self, *args, **kwargs):
                  if not self.is_admin:
                      raise PermissionError("Admin privileges required")
                  return super().admin_method(*args, **kwargs)
          return WrappedClass
      
      @require_admin
      class MyClass:
          def __init__(self, is_admin):
              self.is_admin = is_admin
      
          def admin_method(self):
              print("This is an admin method.")
      
      admin_obj = MyClass(is_admin=True)
      admin_obj.admin_method()  # 正常调用
      
      user_obj = MyClass(is_admin=False)
      user_obj.admin_method()   # 抛出 PermissionError

      类装饰器可以用来在类方法调用前进行数据验证。

      例如,我们可以创建一个装饰器,验证方法参数的类型。

      def validate_params(cls):
          class WrappedClass(cls):
              def method_with_validation(self, x):
                  if not isinstance(x, int):
                      raise ValueError("Parameter x must be an integer")
                  return super().method_with_validation(x)
          return WrappedClass
      
      @validate_params
      class MyClass:
          def method_with_validation(self, x):
              print(f"Received {x}")
      
      obj = MyClass()
      obj.method_with_validation(10)  # 正常调用
      obj.method_with_validation("a") # 抛出 ValueError

      接下来,我们将通过一个综合示例来展示如何使用类装饰器。

      这个示例将包含一个日志记录装饰器、一个权限检查装饰器和一个数据验证装饰器。

      import datetime
      
      def log_activity(cls):
          class WrappedClass(cls):
              def __getattribute__(self, name):
                  attr = super().__getattribute__(name)
                  if callable(attr):
                      def logged(*args, **kwargs):
                          print(f"Calling {name} with arguments {args} and {kwargs} at {datetime.datetime.now()}")
                          result = attr(*args, **kwargs)
                          print(f"{name} returned {result}")
                          return result
                      return logged
                  return attr
          return WrappedClass
      
      def require_permission(permission):
          def decorator(cls):
              class WrappedClass(cls):
                  def __getattribute__(self, name):
                      attr = super().__getattribute__(name)
                      if callable(attr):
                          def secured(*args, **kwargs):
                              if not self.has_permission(permission):
                                  raise PermissionError(f"Permission {permission} required")
                              return attr(*args, **kwargs)
                          return secured
                      return attr
              return WrappedClass
          return decorator
      
      def validate_params(cls):
          class WrappedClass(cls):
              def method_with_validation(self, x):
                  if not isinstance(x, int):
                      raise ValueError("Parameter x must be an integer")
                  return super().method_with_validation(x)
          return WrappedClass
      
      @log_activity
      @require_permission("admin")
      @validate_params
      class MyClass:
          def __init__(self, is_admin):
              self.is_admin = is_admin
      
          def has_permission(self, permission):
              return self.is_admin
      
          def method_with_validation(self, x):
              return f"Received {x}"
      
      # 测试综合示例
      admin_obj = MyClass(is_admin=True)
      print(admin_obj.method_with_validation(10))  # 正常调用
      
      try:
          admin_obj.method_with_validation("a")  # 抛出 ValueError
      except ValueError as e:
          print(e)
      
      user_obj = MyClass(is_admin=False)
      try:
          user_obj.method_with_validation(10)  # 抛出 PermissionError
      except PermissionError as e:
          print(e)

      Calling __init__ with arguments (True,) and {} at 2024-07-11 14:23:45.123456
      __init__ returned None
      Calling method_with_validation with arguments (10,) and {} at 2024-07-11 14:23:45.123456
      method_with_validation returned Received 10
      Received 10
      Calling method_with_validation with arguments ('a',) and {} at 2024-07-11 14:23:45.123456
      Parameter x must be an integer
      Calling __init__ with arguments (False,) and {} at 2024-07-11 14:23:45.123456
      __init__ returned None
      Calling method_with_validation with arguments (10,) and {} at 2024-07-11 14:23:45.123456
      Permission admin required

      1. 日志记录装饰器:记录类的方法调用,包括输入参数和返回值。
      2. 权限检查装饰器:检查用户是否具有调用方法的权限。
      3. 数据验证装饰器:验证方法参数的类型。

      通过这种方式,我们可以在不修改类本身的情况下,为类添加额外的功能。

      类装饰器是 Python 中一个非常强大的工具,可以用来扩展和修改类的行为。通过类装饰器,我们可以在不修改原始代码的情况下为类添加额外的功能。

      在实际开发中,类装饰器有很多应用场景,包括日志记录、访问控制、数据验证等。

      以上为个人经验,希望能给大家一个参考,也希望大家多多支持风君子博客。

      您可能感兴趣的文章:

      • python 自定义装饰器使用及原理详解(最新推荐)
      • Python中的装饰器链(decorator chain)详解
      • python 装饰器带参数和不带参数步骤详解
      • 详解Python如何利用装饰器实现重试机制
      • Python中装饰器和魔法方法的区别解析

      站内搜索