跳到主要内容

Python3 中 is 和 == 有什么区别?

核心区别​

==is
比较内容值是否相等**身份(内存地址)**是否相同
底层调用__eq__() 方法比较 id() 是否相等
可重载✅❌
a = [1, 2, 3]
b = [1, 2, 3]

print(a == b) # True ← 值相等
print(a is b) # False ← 不是同一个对象

print(id(a)) # 140234...
print(id(b)) # 140235...(不同地址)

is 判断的是同一个对象​

a = [1, 2, 3]
b = a # b 和 a 指向同一个对象

print(a == b) # True
print(a is b) # True ← 同一个对象

b.append(4)
print(a) # [1, 2, 3, 4] ← a 也变了

小整数缓存与字符串驻留​

CPython 对小整数(通常 -5 ~ 256)和短字符串做了缓存优化,可能导致 is 返回意外的 True:

# 小整数缓存
a = 100
b = 100
print(a is b) # True ← CPython 复用同一对象

a = 1000
b = 1000
print(a is b) # False ← 超出缓存范围,不同对象

# 字符串驻留
s1 = "hello"
s2 = "hello"
print(s1 is s2) # True ← 短字符串被驻留复用

s1 = "hello world!"
s2 = "hello world!"
print(s1 is s2) # 不确定,依赖解释器实现

注意:不要依赖这种缓存行为来判断值是否相等,应始终用 ==。

is 的正确用法:与单例对象比较​

is 最适合与 None、True、False 这类单例对象比较:

# ✅ 推荐
if value is None:
...

if result is not None:
...

if flag is True:
...

# ❌ 不推荐(虽然通常能工作,但语义不准确)
if value == None:
...

None 在 Python 中是全局唯一的单例,用 is 比较既语义正确,又比 == 少一次方法调用。

__eq__ 可被重载​

== 实际调用左侧对象的 __eq__ 方法,可以自定义:

class AlwaysEqual:
def __eq__(self, other):
return True # 与任何对象都"相等"

obj = AlwaysEqual()
print(obj == 42) # True
print(obj == "abc") # True
print(obj is 42) # False ← is 不受 __eq__ 影响

总结​

  • ==:比较值,调用 __eq__,日常比较用这个
  • is:比较身份(内存地址),仅在判断是否为同一对象时使用
  • 最佳实践:只在与 None、True、False 比较时用 is,其余场景用 ==
  • 不要依赖 CPython 的小整数缓存和字符串驻留来使用 is 比较值