编程后端开发工程师

什么是 Python 中的魔法方法(dunder 方法),它们是如何使用的,以及为什么要在自己的类中重写它们?请给出它们应用的示例,并解释实现时需要考虑的细节。

用 Hintsage AI 助手通过面试

答案。

魔法方法(或称 dunder 方法 – 来自于 double underscore)是特殊的方法,其名称以两个下划线开始和结束,例如 __init____str____add__。它们允许将自定义类的实例嵌入到 Python 的语法和行为中:定义对算术操作、比较、字符串转换、集合协议等的反应。

示例:

class Vector: def __init__(self, x, y): self.x = x self.y = y def __add__(self, other): return Vector(self.x + other.x, self.y + other.y) def __str__(self): return f"Vector({self.x}, {self.y})" v1 = Vector(1, 2) v2 = Vector(3, 4) print(v1 + v2) # 将调用 v1.__add__(v2),返回 Vector(4, 6)

陷阱问题。

如果在自定义类中未实现 __eq__,那么实例之间将如何使用 == 操作符进行比较?

答案: 默认情况下,== 操作符根据身份(内存地址,类似于 is 操作符)来比较对象,如果不重写魔法方法 __eq__

class A: pass print(A() == A()) # False,虽然对象“看上去相同”

由于不了解该主题的细节而导致的真实错误示例。


故事

在一个需要比较图结构的项目中,没有实现 __eq__ 方法。由于在检查“节点是否已添加”时,== 操作符根据 id 而不是内容比较对象,因此得到了不正确的结果。


故事

在编写 REST API 时,通过 str(obj) 将对象序列化为字符串进行日志记录,但忘记定义 __str__。结果输出了不可读的文本 <MyObj object at 0x...>,这妨碍了问题诊断。


故事

在一个数学计算库中,仅实现了 __add__,但忘记了 __iadd__ 用于操作符 +=。因此,表达式 v += w 的表现与预期不符(创建了新对象,而没有更新旧对象),导致在复杂计算中发生内存泄漏。