变量不是盒子,而应该视为一个便利贴。[1]

1. 变量的赋值与复制

当你把一个变量赋值给另一个变量时相当于将两个变量名称贴在同一内存空间上,在修改其中一个的时候另一个的值也随之发生了变化。

In [1]: a = [1,2,3]

In [2]: b = a

In [3]: a.append(4)

In [4]: b
Out[4]: [1, 2, 3, 4]

但是如果对于变量进行重新赋值会导致变量所对应的地址发送变化。

In [5]: list1 = [1,2,3]

In [6]: list2 = list1

In [7]: list2 = [1,2,3,4]

In [8]: list1
Out[8]: [1, 2, 3]

对于list与dictionaries这种复合数据类型,改变其中的值并不会影响到变量的地址,也就出现了这种情况。

In [1]: a = [1,2,3]

In [2]: b = a

In [3]: a.append(4)

In [4]: b
Out[4]: [1, 2, 3, 4]

但是如果我们想要得到两个独立的变量该如何去做呢?Python为我们提供了两个方法,一个是copy另一个为deepcopy,也就是我们常说的深浅复制。

2. 深浅拷贝

In [9]: list1 = [1,2,[3,4]]

In [10]: list2 = list1.copy()

In [11]: list2.append(5)

In [12]: list2
Out[12]: [1, 2, [3, 4], 5]

In [13]: list1
Out[13]: [1, 2, [3, 4]]

这里我们就用来copy的方法实现了浅复制,在改变list2的时候list1并没有发生变化。但是浅拷贝是只是拷贝最外面那一层,但是如果我们修改列表里面的那一层列表会发生什么呢?

In [14]: list2[2].append(7)

In [15]: list1
Out[15]: [1, 2, [3, 4, 7]]

可以看到即使我们使用copy的方法将list1复制到list2,但是这个复制只是浅层的复制,它只赋值了最外层,里面的并没有进行复制。但是如果要获得两个完全独立的列表要怎样做的,那就需要用到deepcopy了,它会将整个数据结构完全复制一份。

In [15]: list1
Out[15]: [1, 2, [3, 4, 7]]

In [16]: from copy import deepcopy

In [17]: list3 = deepcopy(list1)

In [18]: list3[2].append(8)

In [19]: list3
Out[19]: [1, 2, [3, 4, 7, 8]]

In [20]: list1
Out[20]: [1, 2, [3, 4, 7]]>>> list1
[1,2,[3,4,7]]
>>> list3 = deepcopy(list1)
>>> list3[2].append(8)
>>> list3
[1,2,[3,4,7,8]]
>>> list1
[1,2,[3,4,7]]

  1. 流畅的Python(Fluent Python) ↩︎