Day 33 类的装饰器

文章目录

  • [Day 33 类的装饰器](#Day 33 类的装饰器)
    • [1. 类装饰器解决的问题](#1. 类装饰器解决的问题)
    • [2. 函数装饰器 vs. 类装饰器](#2. 函数装饰器 vs. 类装饰器)
    • [3. 设计类装饰器的步骤](#3. 设计类装饰器的步骤)
    • [4. 运行效果与解读](#4. 运行效果与解读)
    • [5. 两种方式定义方法](#5. 两种方式定义方法)
    • [6. 语法糖](#6. 语法糖)

Day 33 类的装饰器

从"动态改造类"的角度再看装饰器:当功能要在多个类之间复用,却又不想回到每个类里修改源码时,类装饰器提供了一种即插即用的方案。

1. 类装饰器解决的问题

  • 同一批类要统一增加日志、统计、鉴权等横切逻辑。
  • 已上线的类不想回头修改源码,只想在外部"套一层"。
  • 需要把增强逻辑抽象出来,供多个类共享。

类装饰器的本质:接收一个类,返回一个被修改过的类,从而在不触碰类定义的情况下完成扩展。

2. 函数装饰器 vs. 类装饰器

维度 函数装饰器 类装饰器
作用对象 函数 / 方法
传入参数 decorator(func) decorator(cls)
返回值 通常是包裹后的函数(闭包) 修改后的类(原类 / 新类)
常见用途 日志、计时、权限验证等 为类批量增加属性、方法,或重写 __init__
核心价值 不修改函数源码即可增强功能 不修改类定义即可扩展行为

理解这张对比表,你就能迅速判断需求是要改函数还是改类。

3. 设计类装饰器的步骤

  1. 接收原始类,并备份需要被替换的方法(常见是 __init__)。
  2. 写一个新方法,在其中加入增强逻辑,然后调用原方法。
  3. 把新方法、额外属性绑定到类(如 cls.log = log_message)。
  4. 返回修改好的类,供外部继续使用。

下面的示例展示了如何一次性为多个类补充日志功能。

python 复制代码
# 定义类装饰器:统一添加日志功能
def class_logger(cls):
    original_init = cls.__init__  # 备份原始构造函数

    def new_init(self, *args, **kwargs):
        print(f"[LOG] 实例化对象: {cls.__name__}")
        original_init(self, *args, **kwargs)

    cls.__init__ = new_init  # 覆写 __init__

    def log_message(self, message):
        print(f"[LOG] {self.__class__.__name__}: {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("这是装饰器添加的日志方法")
复制代码
[LOG] 实例化对象: SimplePrinter
Alice: Hello, World!
[LOG] SimplePrinter: 这是装饰器添加的日志方法

4. 运行效果与解读

  • 实例化时,新版 __init__ 会先打印日志,再调用原构造函数。
  • 原有的 print_text 行为保持不变,保证兼容。
  • 每个被装饰的类都多了一个 log 方法,可以在任何地方调用。

因此,装饰器提供的是一种"批量加功能"的能力。

5. 两种方式定义方法

方式 写法 特点
类内部定义 class 语句块中写 def 语义直观,但类定义后不易扩展
外部赋值 先定义函数,再执行 cls.fn = fn 运行期可随时添加 / 修改方法,装饰器常用

两种方式的本质都一样:把函数对象绑定到类属性上。外部赋值让我们无需打开类的源码就能增强它,这就是类装饰器的威力。

6. 语法糖

@decoratorMyClass = decorator(MyClass) 的简写。即使类早已定义,仍可以手动调用装饰器函数改写它------这意味着旧代码也能被安全地套上新能力。

装饰器的核心目标,是在不破坏原实现的前提下,动态、可控地扩展类或函数。

@浙大疏锦行

相关推荐
zhaoyong22228 分钟前
MySQL 存储过程中字符集与排序规则不匹配导致查询性能下降的解决方案
jvm·数据库·python
sinat_3834373629 分钟前
golang如何从Python转型Go开发_golang从Python转型Go开发攻略
jvm·数据库·python
rockey62738 分钟前
基于AScript的python3脚本语言发布啦!
python·c#·.net·script·python3·eval·expression·function·动态脚本
gqk011 小时前
Python入门
python
Muyuan19981 小时前
28.Paper RAG Agent 开发记录:修复 LLM Rerank 的解析、Fallback 与可验证性
linux·人工智能·windows·python·django·fastapi
代码小书生2 小时前
statistics,一个统计的 Python 库!
开发语言·python
STLearner2 小时前
SIGIR 2026 | LLM × Graph论文总结(图增强LLM,GraphRAG,Agent,多模态,知识图谱,搜索,推
人工智能·python·深度学习·神经网络·机器学习·数据挖掘·知识图谱
FreakStudio2 小时前
MicroPython 内核开发者直接狂喜!这个 Claude 插件市场,把开发全流程做成了「对话式外挂」
python·单片机·嵌入式·面向对象·并行计算·电子diy
老陈说编程2 小时前
12. LangChain 6大核心调用方法:invoke/stream/batch同步异步全解析,新手也能轻松学会
开发语言·人工智能·python·深度学习·机器学习·ai·langchain
给自己做减法3 小时前
rag混合检索
人工智能·python·rag