在 Python 调试过程中,== 和 is 混用导致的 bug 屡见不鲜。这两个看似功能相似的操作符,背后却对应着完全不同的底层逻辑。本文将从官方定义、实际案例、底层原理三个维度,彻底讲清楚它们的区别,帮你避开踩坑。

一、核心定义:值相等 vs 对象同一性

先明确两个核心概念,这是理解区别的基础:

操作符官方定义通俗理解底层判断依据
==Equality(相等性)检查两个对象的内容 / 值是否一致调用对象的 eq() 方法
isIdentity(同一性)检查两个变量是否指向内存中同一个对象

从现象看本质

Case 1:整数(小整数池)

a = 1
b = 1
print(a == b)  # 输出:True(值相等)
print(a is b)  # 输出:True(指向同一个对象)

原因:Python 为了提升性能,会预先创建并缓存「小整数池」(默认范围:-5 ~ 256)。当你给变量赋值为这个范围内的整数时,不会新建对象,而是直接引用缓存中的对象。因此 a 和 b 指向内存中同一个 1。
注意:如果整数超出这个范围(比如 a=1000; b=1000),a is b 通常会返回 False(不同环境可能有差异),但 a == b 仍为 True。

案例 2:浮点数

c = 1.0
d = 1.0
print(c == d)  # 输出:True(值相等)
print(c is d)  # 输出:True(多数环境下,简单浮点数也会缓存)

浮点数的缓存机制不如整数稳定,复杂浮点数(如 1.23456)大概率不会被缓存,此时 is 会返回 False,但 == 始终以值为准。

案例 3:字符串(字符串驻留)

# 简单字符串
e = "abc"
f = "abc"
print(e == f)  # 输出:True
print(e is f)  # 输出:True

# 带空格的字符串
a = "hello world"
b = "hello world"
print(a == b)  # 输出:True
print(a is b)  # 输出:True(多数环境下触发驻留)

原因:
Python 对不可变、简单的字符串会触发「字符串驻留(Interning)」机制 —— 内容相同的字符串共用同一个内存地址,目的是节省内存。但这个机制不是绝对的:
包含特殊字符 / 复杂拼接的字符串(如 “hello” + " world")可能不被驻留;
动态生成的字符串(如 str(123))通常不被驻留。

案例 4:列表(可变对象)

g = [1, 2, 3] 
h = [1, 2, 3]
print(g == h)    # 输出:True(值完全相同)
print(id(g))     # 输出:3108129548864(示例地址)
print(id(h))     # 输出:3108132618432(示例地址)
print(g is h)    # 输出:False(不同内存地址)

原因:列表是可变对象,每次执行 [1,2,3] 时,Python 都会在内存中新建一个独立的列表对象。哪怕内容完全一样,它们也是两个不同的「容器」,因此 id 不同,is 返回 False。

案例 5:直接赋值(引用传递)

a = [1, 2, 3]
b = a  # 将b指向a的内存地址
print(a is b)  # 输出:True(同一个对象)
print(a == b)  # 输出:True(值自然相等)

# 验证:修改b会影响a
b.append(4)
print(a)  # 输出:[1,2,3,4]

结论:b = a 不是复制对象,而是给同一个对象新增一个「别名」(引用)。此时 a 和 b 指向同一块内存,is 必然返回 True。

三、什么时候用 ==?什么时候用 is?

1.判断值是否相等 → 用 ==(90% 的场景)

# 正确用法:判断用户输入是否为"exit"
user_input = input("请输入:")
if user_input == "exit":
    print("退出程序")

2.判断对象是否为同一个 → 用 is(特定场景)

# 正确用法:判断是否为None
if data is None:
    print("数据为空")

# 错误用法(不报错,但不规范)
if data == None:
    pass

四、总结

== 比较值相等,is 比较对象同一性(内存地址);
不可变对象(整数、字符串)可能因 Python 缓存 / 驻留机制,导致内容相同的变量指向同一个对象(is 返回 True),但这是优化行为,不能依赖;
可变对象(列表、字典、集合)只要是新建的(如 []、{}),哪怕内容相同,is 也返回 False;
实际开发中,优先用 == 判断值,仅在判断 None 或验证对象引用时用 is。
掌握 == 和 is 的区别,不仅能避免调试时的坑,更能加深对 Python「一切皆对象」和「引用传递」核心特性的理解。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐