is 比较的是对象身份(内存地址,等价于 id(a) == id(b)),== 比较的是值是否相等,调用左操作数的 __eq__ 方法。两个不同的对象可以值相等,但 is 为 False。

a = [1, 2]; b = [1, 2]
a == b   # True,值相等
a is b   # False,两个不同对象
c = a
c is a   # True,同一对象

使用准则:

  • 与单例比较用 isx is Nonex is True,因为 None 是全进程唯一单例,且 __eq__ 可能被重载出意外行为。
  • 比较值用 ==
  • 自定义类默认 __eq__ 继承自 object,行为等同 is;需要值语义就重写 __eq__(同时通常要重写 __hash__,否则对象不可哈希)。

易错点:小整数(通常 -5~256)和短字符串有缓存/驻留,a = 100; b = 100; a is b 常为 True,但这是 CPython 实现细节,绝不能依赖它做逻辑判断。追问方向:__eq____hash__ 的契约、为什么重载 __eq__ 后 hash 默认失效。