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()  # 输出:当前类作者:你自定义的作者

@浙大疏锦行

相关推荐
rainbow68891 分钟前
Python零基础到精通全攻略
python
毕设源码-朱学姐2 分钟前
【开题答辩全过程】以 基于python网络安全知识在线答题系统为例,包含答辩的问题和答案
开发语言·python·web安全
2301_765703143 分钟前
Python异步编程入门:Asyncio库的使用
jvm·数据库·python
wjs20245 分钟前
PHP Misc
开发语言
Highcharts.js6 分钟前
Next.js 集成 Highcharts 官网文档说明(2025 新版)
开发语言·前端·javascript·react.js·开发文档·next.js·highcharts
CodeByV6 分钟前
【Qt】信号与槽
开发语言·qt
爱学习的阿磊7 分钟前
模板代码跨编译器兼容
开发语言·c++·算法
Dxy12393102167 分钟前
Python判断MySQL表是否存在,不存在则创建
python·mysql·adb
带鱼吃猫11 分钟前
C++STL:从 0 到 1 手写 C++ string以及高频易错点复盘
开发语言·c++
u01092727112 分钟前
代码覆盖率工具实战
开发语言·c++·算法