返回介绍

E.3 =、== 与 is 以及何时只是复制

发布于 2024-01-27 21:43:10 字数 2528 浏览 0 评论 0 收藏 0

在 Python 中,看似相似的函数间有一些重大区别。我们已经了解了一些,但是让我们重新看一下一些代码和输出(使用 IPython):

In [1]: a = 1 ➊

In [2]: 1 == 1 ➋
Out[2]: True

In [3]: 1 is 1 ➌
Out[3]: True

In [4]: a is 1 ➍
Out[4]: True

In [5]: b = []

In [6]: [] == []
Out[6]: True

In [7]: [] is []
Out[7]: False

In [8]: b is []
Out[8]: False

❶ 设置变量 a 为 1。

❷ 检查 1 是否等于 1。

❸ 检查 1 是否与 1 是相同的对象。

❹ 检查 a 是否与 1 是相同的对象。

如果在 IPython 中执行这些代码(这样你可以看到类似于这里展示的输出),你会注意到一些有趣的、可能意外的结果。对于一个整数,我们看到很容易通过多种方式来确定相等。然而对于列表对象,我们发现 is 与其他比较操作符表现得不同。在 Python 中,内存管理操作不同于其他语言。在 Sreejith Kesavan 的博客上(http://foobarnbaz.com/2012/07/08/understanding-python-variables/),有一篇使用可视化技术的文章,讨论了 Python 如何管理内存中的对象。

为了从另外一个视角观察,让我们看一下对象内存的位置:

In [9]: a = 1

In [10]: id(a)
Out[10]: 14119256

In [11]: b = a ➊

In [12]: id(b) ➋
Out[12]: 14119256

In [13]: a = 2

In [14]: id(a) ➌
Out[14]: 14119232

In [15]: c = []

In [16]: id(c)
Out[16]: 140491313323544

In [17]: b = c

In [18]: id(b) ➍
Out[18]: 140491313323544

In [19]: c.append(45)

In [20]: id(c) ➎
Out[20]: 140491313323544

❶ 将 a 赋值给 b。

❷ 当在这里使用 id 方法时,我们发现 b 和 a 都使用了内存中相同的位置,也就是说,它们在内存中是相同的对象。

❸ 当在此时调用 id 方法时,我们发现 a 在内存中拥有了新的地址。这个地址现在保存着值 2。

❹ 在列表中,可以看到我们在赋值后,列表拥有与赋值对象相同的 id。

❺ 当改变这个列表时,我们发现我们不能改变内存中的位置。Python 列表表现得与整数和字符串略有不同。

这里,我们的目的不是让你对 Python 中的内存分配有深入的理解,而是意识到我们可能不会总是去思考我们到底赋值了什么。在处理列表和字典时,我们需要知道和理解的是,在我们将它赋值为一个新变量的时候,新的变量和旧的变量仍然是内存中的相同对象。如果我们改变其中一个,也改变了另一个。如果只想要改变其中一个或另一个,或者需要创建一个新对象作为对象的副本,需要使用 copy 方法。

让我们通过最后一个示例来解释 copy 与赋值:

In [21]: a = {}

In [22]: id(a)
Out[22]: 140491293143120

In [23]: b = a

In [24]: id(b)
Out[24]: 140491293143120

In [25]: a['test'] = 1

In [26]: b ➊
Out[26]: {'test': 1}

In [27]: c = b.copy() ➋

In [28]: id(c) ➌
Out[28]: 140491293140144

In [29]: c['test_2'] = 2

In [30]: c ➍
Out[30]: {'test': 1, 'test_2': 2}

In [31]: b ➎
Out[31]: {'test': 1}

❶ 在这行代码中,我们看到,当我们修改 a 时,同样修改了 b,因为它们存储在内存中相同的位置。

❷ 使用 copy 方法我们创建了一个新的变量,c,这是第一个字典的副本。

❸ 这行代码中,我们看到 copy 创建了一个新的对象。它有一个新的 id。

❹ 在修改了 c 之后,我们看到它现在保存着两个键和值。

❺ 即使在 c 修改之后,我们看到 b 仍然是相同的。

在最后这个示例中,很显然,如果你真的想要一个字典或列表的副本,需要使用 copy 方法。如果你想要相同的对象,那么可以使用 =。类似地,如果你想要知道两个对象是不是“相等的”,可以使用 ==,但是如果你想知道它们是否是相同的对象,则使用 is。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文