摘要:
如果你学过 C 语言,那么当你初见 Python 时可能会觉得 Python 的赋值方式略有诡异:好像差不多,但又好像哪里有点不太对劲。
本文比较并解释了这种赋值逻辑上的差异。回答了为什么需要这种赋值逻辑以及如何使用这种赋值逻辑的问题。
当然,即使未学过 C 语言,也可通过本文更好地了解 Python 的赋值逻辑——这种赋值逻辑影响着 Python 的方方面面,从而可以让你更好地理解和编写 Python 程序。
第一章 引例
先来看一组似乎矛盾的代码:
# 代码 1
>>> a = 3
>>> b = a
>>> b = 5
>>> a
3
这看上去似乎很好理解。第二步中, a
只是把值复制给 b
,然后 b
又被更新为 5
,a
和 b
是两个独立的变量,那么 a
的值当然不会受到影响。
真的是这样吗?
再来看一段代码:
# 代码 2
>>> a = [1, 2, 3]
>>> b = a
>>> b[0] = 1024
>>> a
[1024, 2, 3]
第二步中,a
只是复制把列表复制给 b
,然后更新 b[0]
的值,最后输出 a
,可是 a
竟然也被改变了。
按照代码 1 的逻辑(即变量之间独立),代码 2 的中的 a
不应该受到影响。
为什么出现了这样的差异?
第二章 Python 的“反直觉”
先不解释上面那个“看似矛盾”的问题。
先来看看另一组简单的 Python 代码在内存中是什么样子的:
# 代码 3
b = 3
b = b + 5
它在内存中的操作示意图是这样的:
然而,从代码的的字面意思上看,“把 3 赋给 b,把 b 加 5 之后再赋给 b。”
也就是把代码看成这个样子:
b ← 3
b ← b + 5
所以下面这张在内存中的操作图可能更符合我们的直觉:
也即 b + 5
的值又写回到 b
中。典型的 C 程序就是这样的。为变量 b
分配一个 int
型的内存单元,然后将整数 3
存放在该内存单元中。b
就代表了该块内存空间,不再移动,可以更新 b
的值,但 b
在内存中的地址就不再变化了。所以我们说 b = b + 5
,就等于 b ← b + 5