一文了解 Python 中的对象比较方法 is 和 == 及其本质(上)

简介: 我们在学习基础的时候没听说 Python 有 C 或 C++ 中的指针啊,Python 中指针是什么?先把指针这个概念放一放,一提到指针可能初学 C 和 C++ 的人都害怕(本人也害怕),先来理解一下 Python 里面对象的本质。

1 Python 中的对象 ID

我们在学习基础的时候没听说 Python 有 C 或 C++ 中的指针啊,Python 中指针是什么?


先把指针这个概念放一放,一提到指针可能初学 C 和 C++ 的人都害怕(本人也害怕),先来理解一下 Python 里面对象的本质。


比如下面的代码,当声明 a = 100 和  b = 100 的时候,能发现 id(a) == id(b),为什么 a 和 b 的 id 值是一样的呢?

>>> a = 100
>>> b = 100
>>> id(a)
4343720720
>>> id(b)
4343720720
>>>


我们来看一下这个图:

image.png


利用上图来打一个比喻,可能不是很准确但方便我们进行理解。如果计算机被当成是一栋楼,那么内存空间就相当楼中的每个房间,内存地址就是这个房间的门牌号,这个房间内可以存储数据(比如数字 100 ,数字 10 或者其他类型)。


假如有一天,来了个要租房的小 a,小 a 说:“我看中了门牌号为(内存地址 4343720720 )的这个房间”,并且放心的租用了这个房,所以 a = 100。小 a 就住在了这个房间里,当我们查询 id(a)的时候,计算机就返回给我们这个房间的门牌号(也就是内存地址 4343720720 )。


同理,小 b 也看中了这个房子,并且也放心的住了下来。而且因为房间里存储的数据都是 100,即使虽然 a 和 b 的名字不同,但他们住同一房间,所以内存地址就相同。


再看如下的代码:

>>> a, b = 10, 20
>>> id(a)
4343717840
>>> id(b)
4343718160
>>> a, b = b, a
>>> id(a)
4343718160
>>> id(b)
4343717840
>>>


当声明 a = 10b = 20 的时候,情况发生了改变,这个过程其实也好理解,就是相当于小 a 和小 b 分别看中了不同的房间(小 a 看中的是门牌号 4343717840 的房间,小 b 看中的是门牌号 4343718160 ),当他们住下来后,这个房间存着不同数据( a=10, b=20 )。


当他们进行交换的时候a, b = b, a,就相当于交换了房间,但是房间里的数据是没有变。最后a=20, b =10,因为内存地址 4343717840 存的数字就是 10, 内存地址 4343718160 存的数字是 20。


image.png

2 is 比较符

如上图的例子,我们可以看到,如何确定 a 和 b 是否是一致的呢?通过:

>>> a is b


如果这两个对象确实是内存中的同一个对象将返回 True, 否则不一致就会返回 False 。


什么是对象 id


在 Python 中我们可以通过 id() 函数查看每个对象的内存 id。


  • id(x) 是一个整数
  • id(x) == id(y) 当且仅当 x 和 y 在内存中引用相同的对象时才为真
  • id(x) 在 x 的生命周期内是恒定的,也就说,只要 x 存在,这个内存 id 也是不变的


Python 解释器有许多语言的实现,虽然以上三点在每一种实现的 id() 函数都是正确的,但它们背后的实现方式并不相同。例如 CPython (用 C 语言编写的 Python 解释器),使用对象的内存地址作为它的 id --但不要认为所有的实现都会这样做!


例如,另一个 Python 实现是 Skulpt,这是一个 Python 到 JavaScript 的编译器,Anvil 使用它来在浏览器中运行 Python 客户端代码(这样您就可以为 Web 开发而无需编写 JavaScript)。 JavaScript 中的对象没有稳定的内存地址,JavaScript 也没有为每个对象公开一个稳定的标识符。所以,Skulpt 不能使用对象在内存中的地址作为它的 id。


在本文的其余部分,我们将使用使用 CPython 生成的示例,它确实使用对象的内存地址作为其 id。 CPython 能够做到这一点,因为一旦 CPython 中的对象存在,它就不能在内存中移动。这意味着使用对象的地址作为其 id 将保证该对象的生命周期内的稳定值,不像(例如)Skulpt。


我们来看一个列表的例子:

>>> a = ["Learning", "Python"]
>>> id(a)
1769202632064
>>> b = a
>>> id(a), id(b)
(1769202632064, 1769202632064)
>>> 

我们定义了一个 a 列表,然后通过 b = a 建立指向 a 的新指针,当我们检查他们的 id 时,发现它们的结果是相同的 —— 1769202632064。


接下来,我们使用 copy() 函数来看一下会不会有不同的结果:

>>> c = a.copy()
>>> id(a), id(c)
(1769202632064, 1769171462656)
>>> 


如上所示,a 和 c 有着不同的 id,说明调用 copy() 函数完全生成了一个全新的列表对象。

a is b 的本质

所以本质上来说,说 a is b 直接相当于说 id(a) == id(b) 。当你在两个对象上调用 is 时,Python 会获取它们的 id 并直接比较它们。而已!

>>> a is b
True
>>> 

然而,这还不是故事的结局。 Python 有另一种更灵活的方式来定义对象相等性。

3 == 比较符

在 Python 中,想知道 “a 和 b 是否相同” 的另一种方法是使用如下的代码:

>>> a == b
True
>>> 


就和 is 一样,== 比较符也是返回 True 或 False。但是 Python 决定返回哪个的方式与 is 运算符不同,这意味着 ==is 可以为相同的对象提供不同的结果。


用同样的例子来看结果:

>>> a = ["Learning", "Python"]
>>> b = a
>>> c = a.copy()
>>> a == b
True
>>> a is b
True
>>> a == c
True
>>> a is c
False
>>> 


将看到 a ==c 为 True, 反而 a is c 为 False。为什么?原因是:


  • is 用于两个指针是否指向内存中完全相同的对象
  • == 用于两个对象是否是被看做是相等的
相关文章
|
3月前
|
测试技术 开发者 Python
Python单元测试入门:3个核心断言方法,帮你快速定位代码bug
本文介绍Python单元测试基础,详解`unittest`框架中的三大核心断言方法:`assertEqual`验证值相等,`assertTrue`和`assertFalse`判断条件真假。通过实例演示其用法,帮助开发者自动化检测代码逻辑,提升测试效率与可靠性。
343 1
|
4月前
|
机器学习/深度学习 数据采集 数据挖掘
基于 GARCH -LSTM 模型的混合方法进行时间序列预测研究(Python代码实现)
基于 GARCH -LSTM 模型的混合方法进行时间序列预测研究(Python代码实现)
140 2
|
4月前
|
调度 Python
微电网两阶段鲁棒优化经济调度方法(Python代码实现)
微电网两阶段鲁棒优化经济调度方法(Python代码实现)
128 0
|
4月前
|
传感器 大数据 API
Python数字限制在指定范围内:方法与实践
在Python编程中,限制数字范围是常见需求,如游戏属性控制、金融计算和数据过滤等场景。本文介绍了五种主流方法:基础条件判断、数学运算、装饰器模式、类封装及NumPy数组处理,分别适用于不同复杂度和性能要求的场景。每种方法均有示例代码和适用情况说明,帮助开发者根据实际需求选择最优方案。
208 0
|
4月前
|
Python
Python字符串center()方法详解 - 实现字符串居中对齐的完整指南
Python的`center()`方法用于将字符串居中,并通过指定宽度和填充字符美化输出格式,常用于文本对齐、标题及表格设计。
|
3月前
|
人工智能 数据安全/隐私保护 异构计算
桌面版exe安装和Python命令行安装2种方法详细讲解图片去水印AI源码私有化部署Lama-Cleaner安装使用方法-优雅草卓伊凡
桌面版exe安装和Python命令行安装2种方法详细讲解图片去水印AI源码私有化部署Lama-Cleaner安装使用方法-优雅草卓伊凡
411 8
桌面版exe安装和Python命令行安装2种方法详细讲解图片去水印AI源码私有化部署Lama-Cleaner安装使用方法-优雅草卓伊凡
|
3月前
|
安全 大数据 程序员
Python operator模块的methodcaller:一行代码搞定对象方法调用的黑科技
`operator.methodcaller`是Python中处理对象方法调用的高效工具,替代冗长Lambda,提升代码可读性与性能。适用于数据过滤、排序、转换等场景,支持参数传递与链式调用,是函数式编程的隐藏利器。
128 4
|
4月前
|
机器学习/深度学习 数据采集 算法
【CNN-BiLSTM-attention】基于高斯混合模型聚类的风电场短期功率预测方法(Python&matlab代码实现)
【CNN-BiLSTM-attention】基于高斯混合模型聚类的风电场短期功率预测方法(Python&matlab代码实现)
257 4
|
3月前
|
算法 调度 决策智能
【两阶段鲁棒优化】利用列-约束生成方法求解两阶段鲁棒优化问题(Python代码实现)
【两阶段鲁棒优化】利用列-约束生成方法求解两阶段鲁棒优化问题(Python代码实现)
|
4月前
|
安全 JavaScript Java
Python中None与NoneType的真相:从单例对象到类型系统的深度解析
本文通过10个真实场景,深入解析Python中表示“空值”的None与NoneType。从单例模式、函数返回值,到类型注解、性能优化,全面揭示None在语言设计与实际编程中的核心作用,帮助开发者正确高效地处理“无值”状态,写出更健壮、清晰的Python代码。
415 3

推荐镜像

更多