赋值
python 跟 java 中的变量本质是不一样的, Python 的变量实质上是一个指针(int 型或 str 型), 而 java 的变量是一个可操作的存储空间.
- a = 123
- b = a
- print(id(a))
- print(id(b))
- print(a is b)
- result:
- 26848576
- 26848576
- True
这里可以看到 a 和 b 的地址是一样的, a=123, 实质上是将 a 这个对象 "贴到"123 上; 同样, b=a, 也是将 b 这个对象 "贴到"123 上, 这里变量实际上是个 "便利贴".
下面用一个可变的对象 list 来做说明:
- a = [1, 2, 3]
- b = a
- a.append(4)
- a[0] = 6
- print(a)
- print(b)
- result:
- [6, 2, 3, 4]
- [6, 2, 3, 4]
首先把 a 和 b 贴在 [1,2,3]这个对象上, 然后通过 append,[1,2,3]这个对象变成了 [1,2,3,4], 再通过 a[0]=6, 将对象[1,2,3,4] 的第 0 个元素地址对应值改为 6,
则最终这个对象是[6,2,3,4], 然而 a 和 b 仍然是贴在这个对象上的, 即 a 和 b 都是[6,2,3,4]
浅拷贝(copy)
对于浅拷贝有两种情况:
1. 浅拷贝值是不可变对象 (数值, 字符串, 元组) 时, 等同于赋值, 对象的 id 值与浅拷贝原来的值相同.
- import copy
- a = 1
- b = a
- c = copy.copy(a)
- print(id(a))
- print(id(b))
- print(id(c))
- result:
- 35258712
- 35258712
- 35258712
2. 浅拷贝值是可变对象 (list,dict) 时:
2.1 不包含子对象
- # coding:utf-8
- import copy
- a = [1, 2, 3]
- b = a
- c = copy.copy(a)
- print("append 前 c={}".format(id(c)))
- a.append(4)
- print("a={}".format(id(a)))
- print("b={}".format(id(b)))
- print("append 后 c={}".format(id(c)))
- print("a 值 ={}".format(a))
- print("b 值 ={}".format(b))
- print("c 值 ={}".format(c))
- result:
append 前 c=139982846485352
- a=139982846912272
- b=139982846912272
append 后 c=139982846485352
a 值 =[1, 2, 3, 4]
b 值 =[1, 2, 3, 4]
c 值 =[1, 2, 3]
对于不包含子对象的情况下, 原值的改变并不会影响浅拷贝的值, 同时浅复制的值改变也并不会影响原值, 并且浅拷贝是新开辟的一块内存, 与原对象内存地址不同.
2.2 包含子对象
- # coding:utf-8
- import copy
- a = [1, [4], 2, 3]
- b = a
- c = copy.copy(a)
- print("append 前 c={}".format(id(c)))
- a.append(5)
- a[1].append(9)
- print("a={}".format(id(a)))
- print("b={}".format(id(b)))
- print("append 后 c={}".format(id(c)))
- print("a 值 ={}".format(a))
- print("b 值 ={}".format(b))
- print("c 值 ={}".format(c))
- result:
append 前 c=140519703466856
- a=140519703889752
- b=140519703889752
append 后 c=140519703466856
a 值 =[1, [4, 9], 2, 3, 5]
b 值 =[1, [4, 9], 2, 3, 5]
c 值 =[1, [4, 9], 2, 3]
可以看出, 浅拷贝只拷贝父对象([1,2,3]), 不会拷贝对象内部的子对象([4]), 改变原对象中复杂子对象的值时会改变浅拷贝的值.
深拷贝(deepcopy)
- # coding:utf-8
- import copy
- a = [1, [4], 2, 3]
- print("a 原始值 ={}".format(a))
- b = a
- d = copy.deepcopy(a)
- a.append(5)
- a[1].append(9)
- print("a={}".format(id(a)))
- print("b={}".format(id(b)))
- print("d={}".format(id(d)))
- print("a 值 ={}".format(a))
- print("b 值 ={}".format(b))
- print("d 值 ={}".format(d))
- result:
a 原始值 =[1, [4], 2, 3]
- a=139675956164440
- b=139675956164440
- d=139675955741904
a 值 =[1, [4, 9], 2, 3, 5]
b 值 =[1, [4, 9], 2, 3, 5]
d 值 =[1, [4], 2, 3]
深拷贝则会拷贝对象及其子对象, 深拷贝的时候会将复杂对象的每一层复制一个单独的个体出来, 原对象的值改变时并不会影响 deepcopy 的值,
但是, 由于深拷贝需要维护一个 内存 用于记录已经拷贝的对象, 所以深拷贝的速度会比较慢.
来源: https://www.cnblogs.com/FG123/p/9463390.html