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,同一对象
使用准则:
- 与单例比较用
is:x is None、x is True,因为 None 是全进程唯一单例,且__eq__可能被重载出意外行为。 - 比较值用
==。 - 自定义类默认
__eq__继承自 object,行为等同is;需要值语义就重写__eq__(同时通常要重写__hash__,否则对象不可哈希)。
易错点:小整数(通常 -5~256)和短字符串有缓存/驻留,a = 100; b = 100; a is b 常为 True,但这是 CPython 实现细节,绝不能依赖它做逻辑判断。追问方向:__eq__ 与 __hash__ 的契约、为什么重载 __eq__ 后 hash 默认失效。