
本文介绍如何在不继承、不知晓被包装对象构造细节的前提下,让自定义类自动将所有未定义的方法调用委托给内部封装的对象,核心是利用 Python 的 __getattr__ 魔术方法实现透明代理。
本文介绍如何在不继承、不知晓被包装对象构造细节的前提下,让自定义类自动将所有未定义的方法调用委托给内部封装的对象,核心是利用 python 的 `__getattr__` 魔术方法实现透明代理。
在面向对象设计中,有时我们需要对某个已有对象(如字符串、列表、第三方类实例等)进行轻量级封装,既不想继承它(因构造逻辑未知或不兼容),又希望外部能像直接操作该对象一样调用其全部方法——即实现“方法自动代理”。Python 提供了优雅的解决方案:重写 __getattr__ 方法。
__getattr__ 是 Python 数据模型中的关键魔术方法,仅当属性在常规查找路径(实例字典、类及其父类)中均未找到时才会被调用。这使其成为实现“兜底代理”的理想钩子:我们将所有未显式定义的属性访问(包括方法)动态转发至内部持有的 self.ele 对象。
以下是标准实现:
class A:
def __init__(self, ele):
self.ele = ele
def __getattr__(self, name):
return getattr(self.ele, name)
✅ 效果演示:
# 封装一个字符串
a = A("hello world")
# 直接调用字符串方法 —— 无需在 A 中预先定义
print(a.upper()) # 输出: "HELLO WORLD"
print(a.split()) # 输出: ['hello', 'world']
print(a.replace('o', '0')) # 输出: "hell0 w0rld"
⚠️ 重要注意事项:
- __getattr__ 不会拦截已存在的属性或方法(如 __init__、__str__ 或你在类中明确定义的任何方法)。若需覆盖特定行为,可单独实现;若需无条件转发(包括特殊方法),应使用 __getattribute__(但需格外谨慎,易引发无限递归)。
- 确保 self.ele 不为 None,否则 getattr(None, name) 会抛出 AttributeError;必要时可在 __getattr__ 中添加空值检查并提供更友好的错误提示。
- 此模式创建的是代理(Proxy)对象,而非装饰器或适配器,它保持了原对象的全部接口语义,适合构建 DSL 封装层、API 客户端包装器或运行时策略注入场景。
总结来说,__getattr__ 是 Python 中实现“隐式委托”的简洁而强大的机制。它让类 A 表现出与 ele 几乎一致的行为,同时保留了完全的封装控制权——无需预知 ele 类型,也无需手动同步上百个方法,真正做到了“按需代理,开箱即用”。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











