- 本书赞誉
- 前言
- 目标读者
- 不适合阅读本书的读者
- 本书结构
- 什么是数据处理
- 遇到困难怎么办
- 排版约定
- 使用代码示例
- 致谢
- 第 1 章 Python 简介
- 第 2 章 Python 基础
- 第 3 章 供机器读取的数据
- 第 4 章 处理 Excel 文件
- 第 5 章 处理 PDF 文件 以及用 Python 解决问题
- 第 6 章 数据获取与存储
- 第 7 章 数据清洗:研究、匹配与格式化
- 第 8 章 数据清洗:标准化和脚本化
- 第 9 章 数据探索和分析
- 第 10 章 展示数据
- 第 11 章 网页抓取:获取并存储网络数据
- 第 12 章 高级网页抓取:屏幕抓取器与爬虫
- 第 13 章 应用编程接口
- 第 14 章 自动化和规模化
- 第 15 章 结论
- 附录 A 编程语言对比
- 附录 B 初学者的 Python 学习资源
- 附录 C 学习命令行
- 附录 D 高级 Python 设置
- 附录 E Python 陷阱
- 附录 F IPython 指南
- 附录 G 使用亚马逊网络服务
- 关于作者
- 关于封面
E.3 =、== 与 is 以及何时只是复制
在 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论