Python中==和is有什么区别?身份运算符与相等性判断指南

清欢
清欢
发布时间:2026-10-29| 9人浏览过
原创

深入解析Python中==相等性运算符与is身份运算符的核心区别。涵盖内存模型、id()函数、__eq__()方法、小整数池与字符串驻留陷阱,以及判断None的最佳实践。

在 Python 中,== 与 is 都可以用来进行比较,但它们评判的维度根本不同:== 是相等性运算符(Equality),用于比对两个对象存储的内容(值)是否相等;is 则是身份运算符(Identity),用于判断两个变量是否引用内存中的同一个物理对象。理解两者的底层差异不仅能写出更符合规范的代码,还能有效规避由单例比较和底层常量池缓存引发的逻辑缺陷。

一、核心本质:内容比对与内存指针

Python 中一切皆对象,每个对象在创建后都会拥有唯一的内存地址(Memory Address)、所属类型(Type)以及实际数据(Value)。

当我们使用 == 时,Python 会调用该对象的 __eq__() 魔术方法,由类型自身定义的逻辑来比较两者包含的值。例如两个独立的列表,只要它们的元素顺序和内容一致,== 就会返回 True。

而 is 运算符直接读取变量内部存储的对象指针。它等价于通过内置函数 id() 获取两者的内存标识符并进行比对,即 id(a) == id(b)。只有当两端的变量严格指向内存堆中同一块地址时,is 才会返回 True。

# 示例:相同内容但独立分配的列表
a = [1, 2, 3]
b = [1, 2, 3]
c = a  # 将 a 的引用赋值给 c

print(a == b)  # 输出: True  (内容完全一致)
print(a is b)  # 输出: False (内存地址不同: id(a) != id(b))
print(a is c)  # 输出: True  (指向完全相同的对象)
Python中==和is有什么区别?身份运算符与相等性判断指南
图 1:变量引用指针与内存对象堆模型(展示值相等与同一物理实体的本质差异)

二、直觉陷阱:为什么有时候 is 会误报“相等”?

在刚学习 Python 时,很多开发者在交互式环境(REPL)中测试过以下代码:

x = 100
y = 100
print(x is y)  # 返回 True!很多初学者因此误以为 is 也能用来比对数字

然而,如果把数字改成更大的值:

m = 1000
n = 1000
print(m == n)  # 输出: True
print(m is n)  # 在终端逐行输入时输出: False

这种“时而 True、时而 False”的现象并非语言规则在摇摆,而是由于官方 CPython 解释器在底层采用的性能优化机制:小整数对象池(Small Integer Cache)。

  • 小整数池机制:在 CPython 启动时,解释器会自动在内存中预先创建 [-5, 256] 范围内的所有整数对象,并将其设为全局单例。所有赋值给该范围内数字的变量,都会直接复用这个已存在的单例地址。因此 100 is 100 得到 True 纯粹是缓存命中带来的附带效果。
  • 超出范围的整数:超出 [-5, 256] 的数字在运行时通常会重新分配堆内存,产生独立的物理对象。
  • 字符串驻留机制(String Interning):长度较短且仅包含下划线、字母和数字的字符串也可能被自动放入驻留池以减少内存占用。
Python中==和is有什么区别?身份运算符与相等性判断指南
图 2:CPython 缓存机制与驻留陷阱解析(展示小整数单例复用与大整数独立内存分配)
版本警示:从 Python 3.8 开始,如果对字面量(如整数、浮点数或字符串)使用 is 操作符,编译器会主动发出语法警告:SyntaxWarning: "is" with a literal. Did you mean "=="?。请切记,缓存优化是底层细节,业务代码绝对不能对此产生依赖。

三、规范指南:什么时候用 is,什么时候用 ==?

在实际工程开发中,选择 is 还是 == 有着极其严格且清晰的决策边界:

1. is 的标准应用:单例判断(尤其是 None)

官方 PEP 8 编码规范明确要求:判断变量是否为 None 时,必须使用 is 或 is not,严禁使用 ==。

# 正确做法:推荐使用 is
if val is None:
    pass

# 错误做法:禁止使用 ==
if val == None:
    pass

为什么要这样规定?原因主要有三点:

  1. 绝对单例:在 Python 运行时中,None 是 NoneType 唯一的单例实例,全局只存在一个物理地址。
  2. 性能极致:is 是一条单一的底层字节码指令(IS_OP),只需比对两个 64 位指针地址;而 == 必须进行方法查找并执行 __eq__() 调用,开销显著增加。
  3. 安全性与防篡改:如果某个第三方类重写了 __eq__() 并始终返回 True,当使用 val == None 时就会引发致命的误判;而 is 的判定逻辑不可被任何用户代码重写。
Python中==和is有什么区别?身份运算符与相等性判断指南
图 3:运算符选择步骤流程图(区分单例检查与业务数据比对的推导过程)

2. == 的标准应用:数值、文本与容器比较

除了单例对象外,所有涉及业务逻辑的数据比对一律使用 ==:

  • 比较数字大小相等性(如 score == 100)。
  • 比较字符串文本内容(如 username == "admin")。
  • 比较列表、字典、集合等数据结构中存储的具体元素。

四、进阶思考:自定义类中的比较机制

在自定义类中,Python 默认的行为是:如果没有显式实现 __eq__() 方法,类会继承自基类 object 的比较逻辑。而在基类 object 中,__eq__() 的默认行为就是比对 is。

这意味着,两个拥有完全相同属性的自定义对象,在没有重写 __eq__() 时,使用 == 也会返回 False:

# 未重写 __eq__ 的自定义类
class PointDefault:
    def __init__(self, x, y):
        self.x = x
        self.y = y

p1 = PointDefault(1, 2)
p2 = PointDefault(1, 2)
print(p1 == p2)  # 返回 False (继承 object.__eq__,退化为比对内存地址)

# 正确重写 __eq__ 的自定义类
class PointCustom:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __eq__(self, other):
        if not isinstance(other, PointCustom):
            return False
        return self.x == other.x and self.y == other.y

cp1 = PointCustom(1, 2)
cp2 = PointCustom(1, 2)
print(cp1 == cp2)  # 返回 True (成功比较坐标内容)
print(cp1 is cp2)  # 返回 False (物理内存上依然是两个独立对象)
Python中==和is有什么区别?身份运算符与相等性判断指南
图 4:== 与 is 核心技术维度矩阵对比(从比较目标到运行性能的完整技术特征)

五、常见疑问与编码注意事项

Q1: a is not b 和 not (a is b) 有什么区别?

两者逻辑结果完全相同,但 is not 是 Python 内置的复合操作符,直接对应一条专门的字节码指令,可读性更好且执行效率更高。编写代码时应当始终使用 if x is not None: 而非 if not x is None:。

Q2: 布尔值判断可以用 is True 吗?

虽然 True 和 False 也是单例对象,可以使用 is,但通常更推荐直接利用布尔求值机制:编写 if condition: 或 if not condition:。只有在需要严格区分布尔值 True 与非零真值(如数字 1)时,使用 if val is True: 才有实际意义。

总结提炼: 记住一条核心标准——只要判断的是“是不是同一个东西”(如 None 和单例),用 is;只要判断的是“里面的值相不相等”,用 ==。遵循这一准则,就能彻底远离 Python 对象比较中的隐藏陷阱。
相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。