Python 特殊方法
特殊方法(dunder)让对象接入语言协议:构造、展示、运算、容器、上下文与异步钩子。
#type / concept
#status / growing
#tech / dev
#resource / python
#tech / lang / python
[!info] 关联笔记
Python 特殊方法
这个概念为什么出现
你希望 len(order_book)、item in book、with lock: 对自定义类型生效。Python 不靠接口声明表,而靠实现约定的 __xxx__ 特殊方法 接入语法与内置函数。
[!abstract] 一句话理解 特殊方法是对象协议钩子:解释器在语法/内置场景调用它们,使自定义类型表现得像内置对象。
最小可运行示例
先把示例放进业务场景,再看代码:
场景:购物车支持 len、in 与可读 repr
# cart_dunder_demo.py
# 业务意图:让 Cart 接入 len/in/repr 协议。
# 教学点:
# - __init__/__repr__;
# - __len__/__contains__;
# - 协议比名义继承更重要。
class Cart:
def __init__(self, user_id: str, items: list[str] | None = None) -> None:
self.user_id = user_id
self._items = list(items or [])
def add(self, sku: str) -> None:
self._items.append(sku)
def __len__(self) -> int:
return len(self._items)
def __contains__(self, sku: object) -> bool:
return sku in self._items
def __repr__(self) -> str:
return f"Cart(user_id={self.user_id!r}, items={self._items!r})"
def main() -> None:
cart = Cart("u1", ["SKU-1"])
cart.add("SKU-2")
print(repr(cart))
print("len:", len(cart))
print("has SKU-2:", "SKU-2" in cart)
if __name__ == "__main__":
main()
建议运行:
python cart_dunder_demo.py
期望输出:
Cart(user_id='u1', items=['SKU-1', 'SKU-2'])
len: 2
has SKU-2: True
结合场景再看三个关注点
len(cart)调用__len__,不是普通方法名。in走__contains__(否则可能退化迭代探测)。repr面向开发者调试,应信息充分且尽量无歧义。
核心概念与准确模型
| 领域 | 例子 |
|---|---|
| 构造/生命周期 | __new__ __init__ __del__ |
| 展示 | __repr__ __str__ |
| 比较 | __eq__ __lt__ … |
| 容器 | __len__ __getitem__ __iter__ __contains__ |
| 数值 | __add__ __radd__ … |
| 上下文 | __enter__ __exit__ |
| 可调用 | __call__ |
| 异步 | __aenter__ __await__ … |
调用约定:优先通过内置/语法触发(len(x)),不要到处手写 x.__len__()。
边界情况与反直觉行为
__eq__与哈希:可变对象重载相等要谨慎__hash__。__getattr__vs__getattribute__:后者是全链路,易误用。- 返回
NotImplemented让反射运算有机会尝试。
常见误区
[!warning] 常见误区:特殊方法是“魔法随便加” 错误理解:加越多越强大。
正确模型:只实现真正需要的协议;错误实现会破坏通用代码假设。
工程实践
- 至少提供有用
__repr__ - 容器协议成组实现
- 上下文管理器优先
contextlib
本节总结
特殊方法是 Python 面向协议编程的核心。实现协议比堆名义继承更地道。
自测题
len(obj)与obj.__len__()更推荐哪个?- 为什么
__repr__重要?
参考答案
len(obj)——走官方协议路径。- 调试与日志可读;容器/异常中大量依赖 repr。
延伸阅读与资料来源
| 资料 | 类型 | 支撑内容 |
|---|---|---|
| Data model | 规范 | 特殊方法全集 |