Python 中这七个类装饰器技巧,装饰类而不是方法!

开发
今天咱们聊聊Python中的类装饰器,但不是常见的函数装饰器哦,而是专门用来装饰类的技巧!很多初学者可能只知道装饰器可以修饰方法或函数,其实它还能“改造”整个类呢。

大家好!今天咱们聊聊Python中的类装饰器,但不是常见的函数装饰器哦,而是专门用来装饰类的技巧!很多初学者可能只知道装饰器可以修饰方法或函数,其实它还能“改造”整个类呢。比如给类动态添加属性、实现单例模式、甚至优化日志系统等功能,都可以通过类装饰器完成。接下来我会用7个小节详细讲解,从基础到高级,手把手教你掌握这些技巧!

一、理解装饰器的基本概念与作用

1. 装饰器是什么?

装饰器是Python中非常强大的工具,它允许我们在不修改原有代码的情况下为函数或类添加额外的功能。比如,你想在函数执行前后打印日志,装饰器就能轻松搞定!来看个简单例子:

def my_decorator(func):
    def wrapper():
        print("执行前的操作")
        func()
        print("执行后的操作")
    return wrapper

@my_decorator
def say_hello():
    print("Hello!")

say_hello()
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.

输出:

执行前的操作
Hello!
执行后的操作
  • 1.
  • 2.
  • 3.

装饰器的核心就是“包装”函数,让它变得更强大。接下来,我们会深入学习如何用装饰器来装饰类,而不是方法哦!

二、使用类装饰器的基本语法

1. 类装饰器的定义与作用

类装饰器其实很好理解!它本质上是一个带有 __call__ 方法的类,可以用来“包装”其他类。当一个类被装饰时,装饰器会拦截对这个类的所有实例化操作。举个例子:

class MyDecorator:
    def __init__(self, cls):# 接收被装饰的类
        self.cls = cls

    def __call__(self, *args, **kwargs):# 拦截实例化操作
        print("类装饰器被调用了!")
        return self.cls(*args, **kwargs)

@MyDecorator  # 等价于 MyClass = MyDecorator(MyClass)
class MyClass:
    def __init__(self, name):
        self.name = name

obj = MyClass("Python")  # 输出:类装饰器被调用了!
print(obj.name)  # 输出:Python
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.

这段代码展示了类装饰器的基本结构和用法。简单来说,装饰器通过 __call__ 方法控制类的实例化过程。是不是很酷?

三、类装饰器中__init__和__call__方法的使用技巧

1. 理解__init__和__call__的作用

在类装饰器中,__init__用于初始化装饰器本身的参数,而__call__则负责对被装饰的类进行处理。两者配合可以让类装饰器功能更强大!来看个例子:

class MyDecorator:
    def __init__(self, func):
        # 初始化时接收被装饰的类
        self.func = func

    def __call__(self, *args, **kwargs):
        # 在这里可以修改类的行为
        print("装饰器执行前的操作")
        instance = self.func(*args, **kwargs)  # 实例化被装饰的类
        print("装饰器执行后的操作")
        return instance


@MyDecorator
class MyClass:
    def __init__(self, name):
        self.name = name


obj = MyClass("Python")  # 输出:装饰器执行前的操作 装饰器执行后的操作
print(obj.name)  # 输出:Python
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.

通过这段代码,你可以清楚地看到装饰器如何在类实例化前后添加额外逻辑!

四、如何通过类装饰器添加属性或方法

1. 类装饰器可以轻松扩展类功能

有时候,我们希望在不修改原始类代码的情况下,为类动态添加属性或方法。这时候,类装饰器就派上用场了!下面是一个简单的例子:

class AddFeatures:
    def __init__(self, cls):
        self.cls = cls  # 接收被装饰的类

    def __call__(self, *args, **kwargs):
        instance = self.cls(*args, **kwargs)  # 创建实例
        
        # 动态添加属性
        instance.new_attribute = "我是新增的属性"
        
        # 动态添加方法
        def new_method(self):
            return"我是新增的方法"
        
        instance.new_method = new_method.__get__(instance)  # 绑定方法到实例
        
        return instance


@AddFeatures
class MyClass:
    def __init__(self, name):
        self.name = name


obj = MyClass("测试")
print(obj.new_attribute)  # 输出:我是新增的属性
print(obj.new_method())  # 输出:我是新增的方法
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.

2. 这段代码的工作原理

  • AddFeatures 是一个类装饰器,它接收一个类作为参数。
  • 在 __call__ 方法中,我们创建了被装饰类的实例。
  • 然后通过直接赋值的方式为实例添加了一个新属性 new_attribute 和一个新方法 new_method。
  • 最后返回这个增强后的实例。

这种方式非常适合在开发中动态扩展类的功能,而无需修改原始类的定义!是不是很酷?

五、利用类装饰器实现单例模式的设计

1. 单例模式是什么?

单例模式是一种设计模式,确保一个类只有一个实例,并提供全局访问点。在 Python 中,我们可以通过类装饰器来实现这一功能!

2. 使用类装饰器实现单例模式

下面是一个简单的例子,展示如何通过类装饰器实现单例模式:

class Singleton:  # 定义一个类装饰器
    def __init__(self, cls):
        self._cls = cls  # 保存被装饰的类
        self._instance = None# 初始化实例为None

    def __call__(self, *args, **kwargs):# 每次调用类时触发
        if self._instance isNone:  # 如果没有创建过实例
            self._instance = self._cls(*args, **kwargs)  # 创建实例
        return self._instance  # 返回唯一实例


@Singleton  # 使用类装饰器
class DatabaseConnection:
    def __init__(self, url):
        self.url = url

# 测试代码
db1 = DatabaseConnection("http://example.com")
db2 = DatabaseConnection("http://test.com")

print(db1 is db2)  # 输出:True
print(db1.url)  # 输出:http://example.com
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.

3. 代码解析

  • Singleton 类是装饰器,它会在第一次调用时创建类的实例,并保存下来。
  • 后续每次调用都会返回同一个实例,确保了单例模式的实现。

在实际开发中,这种技巧非常适合管理数据库连接、配置文件等需要共享资源的场景!

六、高级技巧:动态修改类的行为与功能

1. 使用类装饰器动态添加方法

类装饰器可以用来动态地为类添加方法,而不需要直接修改类的定义。比如下面这个例子:

def add_method(cls):
    def new_method(self):
        return "This is a dynamically added method!"
    cls.dynamic_method = new_method  # 动态添加方法
    return cls

@add_method
class MyClass:
    pass

obj = MyClass()
print(obj.dynamic_method())  # 输出: This is a dynamically added method!
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.

通过类装饰器,我们成功为 MyClass 添加了一个新方法 dynamic_method。

2. 修改类的属性或行为

除了添加方法,类装饰器还能修改类的属性或行为。看这个例子:

def modify_class(cls):
    cls.modified_attribute = "Modified by decorator"
    return cls

@modify_class
class AnotherClass:
    original_attribute = "Original value"

print(AnotherClass.original_attribute)  # 输出: Original value
print(AnotherClass.modified_attribute)  # 输出: Modified by decorator
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.

在这个例子中,我们用装饰器给 AnotherClass 增加了一个新的属性 modified_attribute。

3. 动态注入日志功能

高级一点的应用是为类注入日志功能,方便调试和监控:

import logging

def log_calls(cls):
    original_init = cls.__init__
    def new_init(self, *args, **kwargs):
        logging.info(f"Initializing {cls.__name__} with args={args}, kwargs={kwargs}")
        original_init(self, *args, **kwargs)
    cls.__init__ = new_init
    return cls

@log_calls
class LoggedClass:
    def __init__(self, value):
        self.value = value

logging.basicConfig(level=logging.INFO)
LoggedClass(42)  # 控制台输出: INFO:root:Initializing LoggedClass with args=(42,), kwargs={}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.

通过这个装饰器,每次实例化 LoggedClass 时都会记录日志,非常实用!

七、实战案例:使用类装饰器优化日志记录系统

1. 类装饰器实现日志记录功能

在开发中,日志记录是不可或缺的一部分。通过类装饰器,我们可以优雅地为类添加日志功能。比如,当一个类被实例化或方法被调用时,自动记录相关信息。

class LogDecorator:
    def __init__(self, cls):
        self.cls = cls

    def __call__(self, *args, **kwargs):
        print(f"Creating instance of {self.cls.__name__}")
        instance = self.cls(*args, **kwargs)
        return instance


@LogDecorator
class Calculator:
    def add(self, a, b):
        return a + b


calc = Calculator()  # 输出: Creating instance of Calculator
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.

2. 动态记录方法调用

我们还可以进一步扩展类装饰器,记录类中每个方法的调用情况。

class MethodLogger:
    def __init__(self, cls):
        self.cls = cls
        self._wrap_methods()

    def _wrap_methods(self):
        for attr_name, attr_value in self.cls.__dict__.items():
            if callable(attr_value):
                setattr(self.cls, attr_name, self._log_and_call(attr_value))

    def _log_and_call(self, func):
        def wrapper(*args, **kwargs):
            print(f"Calling {func.__name__} with args: {args}, kwargs: {kwargs}")
            return func(*args, **kwargs)
        return wrapper

    def __call__(self, *args, **kwargs):
        return self.cls(*args, **kwargs)


@MethodLogger
class MathOperations:
    def add(self, a, b):
        return a + b

    def multiply(self, a, b):
        return a * b


math = MathOperations()
math.add(5, 3)  # 输出: Calling add with args: (5, 3), kwargs: {}
math.multiply(4, 6)  # 输出: Calling multiply with args: (4, 6), kwargs: {}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.

这种实战技巧不仅可以帮助我们快速定位问题,还能让代码更加清晰、易维护!

责任编辑:赵宁宁 来源: 手把手PythonAI编程
相关推荐

2022-06-15 10:24:13

Pytho装饰器代码

2024-05-20 09:26:42

Python装饰器函数

2020-11-17 09:10:44

装饰器

2022-09-07 10:20:05

Python装饰类

2010-02-01 17:50:32

Python装饰器

2024-11-06 16:13:00

Python单例模式

2025-01-10 08:38:16

2023-02-07 07:47:52

Python装饰器函数

2024-09-12 15:32:35

装饰器Python

2016-11-01 09:24:38

Python装饰器

2022-10-24 07:31:53

Python编程装饰器

2021-04-11 08:21:20

Python@property装饰器

2025-01-22 15:58:46

2024-05-10 12:33:06

flask装饰器

2021-06-01 07:19:58

Python函数装饰器

2022-09-19 23:04:08

Python装饰器语言

2025-04-18 08:50:57

项目装饰器日志

2023-04-19 15:29:53

通信技巧Vue 3开发

2024-02-26 00:00:00

TypeScript装饰器decorators

2024-03-12 10:02:31

Python内存编程
点赞
收藏

51CTO技术栈公众号