Day 31 类的装饰器

类装饰器本质上是一个可调用对象(通常是函数),它接收被装饰的类作为参数,对这个类进行修改(比如添加属性、方法,或修改现有行为),最后返回修改后的类(或一个新类)。

1.简单示例(无参数):

python 复制代码
# 定义类装饰器:为类添加日志功能
def class_logger(cls):
    # 保存原始的 __init__ 方法
    original_init = cls.__init__

    def new_init(self, *args, **kwargs):
        # 新增实例化日志
        print(f"[LOG] 实例化对象: {cls.__name__}")
        original_init(self, *args, **kwargs)  # 调用原始构造方法

    # 将类的 __init__ 方法替换为新方法
    cls.__init__ = new_init

    # 为类添加一个日志方法(示例)
    def log_message(self, message):
        print(f"[LOG] {message}")

    cls.log = log_message  # 将方法绑定到类,这是一种将外部函数添加为类的属性的方法
    return cls


# 定义简单打印类,应用装饰器
# 同样是语法糖的写法
@class_logger
class SimplePrinter:
    def __init__(self, name):
        self.name = name  # 构造方法:初始化名称

    def print_text(self, text):
        """简单打印方法"""
        print(f"{self.name}: {text}")


# 使用示例
printer = SimplePrinter("Alice")  # 实例化时触发装饰器的日志
printer.print_text("Hello, World!")  # 调用普通方法
printer.log("这是装饰器添加的日志方法")  # 调用装饰器新增的方法

2.带参数的装饰器:

如果需要给类装饰器传递参数,需要多一层嵌套函数:

python 复制代码
# 带参数的类装饰器:自定义添加的属性值
def add_custom_info(author, version):
    # 外层函数接收装饰器参数
    def decorator(cls):
        # 内层函数接收被装饰的类
        cls.author = author
        cls.version = version
        
        def show_info(self):
            print(f"类名:{self.__class__.__name__}")
            print(f"作者:{cls.author},版本:{cls.version}")
        
        cls.show_info = show_info
        return cls
    return decorator

# 使用带参数的装饰器
@add_custom_info(author="你", version="2.0")
class MyClass2:
    def __init__(self, name):
        self.name = name

# 测试
obj2 = MyClass2("带参数的类")
print(obj2.version)  # 输出:2.0
obj2.show_info()
# 输出:
# 类名:MyClass2
# 作者:你,版本:2.0

其中,self.__class__.__name__ 的作用就是:在类的实例方法中,获取当前对象所属类的名称(字符串)。其与type(self).__name__和类名.__name__作用一致,优势是动态性,能适配继承场景。

python 复制代码
class User:
    def show_fixed_name(self):
        # 固定指向User类,即使子类调用也不会变
        print(f"固定类名:{User.__name__}")
    
    def show_dynamic_name(self):
        # 动态指向实例实际所属的类
        print(f"动态类名:{self.__class__.__name__}")

class Admin(User):
    pass

admin = Admin()
admin.show_fixed_name()    # 输出:固定类名:User
admin.show_dynamic_name()  # 输出:动态类名:Admin

3.也可用类定义装饰器

python 复制代码
class ClassDecorator:
    def __init__(self, author="默认作者"):
        # 接收装饰器参数
        self.author = author
    
    def __call__(self, cls):
        # __call__方法接收被装饰的类
        cls.author = self.author
        
        def show_author(self):
            print(f"当前类作者:{self.author}")
        
        cls.show_author = show_author
        return cls

# 使用类装饰器(无参数)
@ClassDecorator()
class MyClass3:
    pass

# 使用类装饰器(有参数)
@ClassDecorator(author="你自定义的作者")
class MyClass4:
    pass

# 测试
obj3 = MyClass3()
obj3.show_author()  # 输出:当前类作者:默认作者

obj4 = MyClass4()
obj4.show_author()  # 输出:当前类作者:你自定义的作者

@浙大疏锦行

相关推荐
AI探索者21 小时前
LangGraph StateGraph 实战:状态机聊天机器人构建指南
python
AI探索者21 小时前
LangGraph 入门:构建带记忆功能的天气查询 Agent
python
FishCoderh1 天前
Python自动化办公实战:批量重命名文件,告别手动操作
python
躺平大鹅1 天前
Python函数入门详解(定义+调用+参数)
python
曲幽1 天前
我用FastAPI接ollama大模型,差点被asyncio整崩溃(附对话窗口实战)
python·fastapi·web·async·httpx·asyncio·ollama
两万五千个小时1 天前
落地实现 Anthropic Multi-Agent Research System
人工智能·python·架构
哈里谢顿1 天前
Python 高并发服务限流终极方案:从原理到生产落地(2026 实战指南)
python
用户8356290780512 天前
无需 Office:Python 批量转换 PPT 为图片
后端·python
markfeng82 天前
Python+Django+H5+MySQL项目搭建
python·django
GinoWi2 天前
Chapter 2 - Python中的变量和简单的数据类型
python