如何使用 Decorator 装饰器来增强类的功能并实现元编程?

如何使用 Decorator 装饰器来增强类的功能并实现元编程?
最新回答
蓝雨希

2020-09-10 18:39:30

在 Python 中,Decorator(装饰器) 是一种强大的元编程工具,可用于动态增强类或方法的功能,而无需修改原始代码。通过装饰器,可以实现日志记录、计时、权限控制、自动注册子类等高级功能。以下是具体实现方法和示例:

1. 使用类装饰器增强类功能

类装饰器接收一个类作为参数,返回修改后的类或新类,适用于在类定义时注入通用逻辑(如自动添加方法、注册子类等)。

示例 1:自动添加 __repr__ 方法def add_repr(cls): def __repr__(self): return f"{cls.__name__}({', '.join(f'{k}={v}' for k, v in self.__dict__.items())})" cls.__repr__ = __repr__ return cls@add_reprclass Person: def __init__(self, name, age): self.name = name self.age = agep = Person("Alice", 30)print(p) # 输出: Person(name=Alice, age=30)
  • 原理:装饰器 add_repr 为类动态添加 __repr__ 方法,生成更易读的字符串表示。
示例 2:自动注册子类registry = []def register(cls): registry.append(cls) return cls@registerclass ServiceA: pass@registerclass ServiceB: passprint(registry) # 输出: [<class '__main__.ServiceA'>, <class '__main__.ServiceB'>]
  • 用途:常用于插件系统或框架,自动发现可用组件。
2. 使用方法装饰器增强方法功能

方法装饰器用于修饰类的特定方法,实现计时、缓存、权限控制等功能。结合 functools.wraps 可保留原方法的元信息(如 __name__)。

示例 1:计时装饰器import timefrom functools import wrapsdef timer(func): @wraps(func) def wrapper(*args, kwargs): start = time.time() result = func(*args, kwargs) # 修正:原代码中 args 错误传递为元组 duration = time.time() - start print(f"{func.__name__} 执行耗时: {duration:.4f} 秒") return result return wrapperclass DataProcessor: @timer def process(self): time.sleep(1) return "处理完成"dp = DataProcessor()dp.process() # 输出执行时间
  • 修正点:原代码中 func(args, kwargs) 应改为 func(*args, kwargs),否则参数会以元组形式传递导致错误。
  • 作用:统计方法执行时间,适用于性能监控。
示例 2:日志装饰器from functools import wrapsdef logged(func): @wraps(func) def wrapper(*args, kwargs): print(f"调用 {func.__name__}") return func(*args, kwargs) return wrapperclass Calculator: @logged def add(self, a, b): return a + bcalc = Calculator()calc.add(2, 3) # 输出: 调用 add
  • 优势:通过 @wraps 保留原方法的 __name__ 和文档字符串,避免调试困难。
3. 结合元编程实现高级控制

装饰器可访问类的属性和方法,实现类似元类的功能(如验证类结构、动态修改行为),但更简洁。

示例:验证类属性def validate_attributes(required_attrs): def decorator(cls): for attr in required_attrs: if not hasattr(cls, attr): raise AttributeError(f"类 {cls.__name__} 缺少必需属性 {attr}") return cls return decorator@validate_attributes(["name", "age"])class Person: def __init__(self, name, age): self.name = name self.age = age# 正确执行p = Person("Alice", 30)# 若删除 name 或 age 属性,会触发 AttributeError
  • 用途:强制要求类实现特定属性或方法,确保结构一致性。
4. 关键点总结
  • 类装饰器:通过修改类本身(如添加方法、注册子类)实现功能增强。
  • 方法装饰器:通过包装方法实现计时、日志等横切关注点。
  • functools.wraps:保留原方法的元信息,提升可维护性。
  • 元编程能力:装饰器可在类创建过程中介入,动态修改行为,适用于框架设计。
5. 实际应用场景
  • 日志与调试:记录方法调用和执行时间。
  • 权限控制:检查用户权限后再执行方法。
  • 缓存:对频繁调用的方法结果进行缓存。
  • 插件系统:自动注册和发现子类。

通过合理使用装饰器,可以编写出更清晰、可复用的代码,同时支持灵活的元编程需求。