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

@浙大疏锦行

相关推荐
DsirNg2 小时前
JavaScript 事件循环机制详解及项目中的应用
开发语言·javascript·ecmascript
研☆香2 小时前
深入解析JavaScript的arguments对象
开发语言·前端·javascript
zzzgw_20012 小时前
io_uring的机理和跟epoll的对比
java·开发语言
MasonYyp2 小时前
简单使用Argos翻译框架
python
XiaoMu_0012 小时前
验证码识别系统
python·深度学习
AuroraWanderll2 小时前
C++类和对象--访问限定符与封装-类的实例化与对象模型-this指针(二)
c语言·开发语言·数据结构·c++·算法
一只小bit2 小时前
Qt Widget 控件介绍:覆盖常用属性及API
开发语言·c++·qt·命令模式·cpp
white-persist2 小时前
网络空间安全核心领域技术架构深度解析
c语言·开发语言·网络·python·安全·网络安全·架构
qq_463944863 小时前
如何修改Anaconda虚拟环境的名字?
开发语言·python·anaconda