赞
踩
先来了解两个重要的概念:
为了弄明白赋值,浅拷贝,深拷贝的差异,下面将通过实例来分析。
- # 可变对象
- obj = [1, 2, 3]
- a = obj
-
- print("原对象obj:", obj, id(obj))
- print("赋值对象a:", a, id(a))
-
- ------------------------------------------------------------------------
- 运行结果:
- 原对象obj: [1, 2, 3] 2211245785600
- 赋值对象a: [1, 2, 3] 2211245785600
分析运行结果可知,赋值对象a跟原对象obj的值相同,内存地址相同。
(1)如果对象obj发生改变,赋值的对象a会发生怎样的变化?
- # 可变对象
- obj = [1, 2, 3]
- a = obj
-
- print("原对象obj:", obj, id(obj))
- print("赋值对象a:", a, id(a))
-
- print("修改对象obj后:")
- obj.append(4)
- print("原对象obj:", obj, id(obj))
- print("赋值对象a:", a, id(a))
-
- ------------------------------------------------------------------------------
- 运行结果:
- 原对象obj: [1, 2, 3] 1896687337984
- 赋值对象a: [1, 2, 3] 1896687337984
- 修改对象obj后:
- 原对象obj: [1, 2, 3, 4] 1896687337984
- 赋值对象a: [1, 2, 3, 4] 1896687337984
分析运行结果可知,原对象obj的值发生改变后,赋值对象a的值也跟着改变了,但是他们的内存地址并不会改变。
- # 不可变对象
- obj = (1, 2, 3)
- a = obj
-
- print("原对象obj:", obj, id(obj))
- print("赋值对象a:", a, id(a))
-
- ---------------------------------------------------------------------------------
- 运行结果:
- 原对象obj: (1, 2, 3) 2408442060864
- 赋值对象a: (1, 2, 3) 2408442060864
分析运行结果可知,赋值对象a跟原对象obj的值相同,内存地址相同。
小结:
赋值只是创建了一个原对象的引用对象,并不会开辟新的内存地址。
原对象发生改变,赋值对象的值也会同步变化,内存地址不变。
- import copy
-
- # 可变对象
- obj = [1, 2, 3]
- b = copy.copy(obj)
-
- print("原对象obj:", obj, id(obj))
- print("浅拷贝对象b:", b, id(b))
-
- ------------------------------------------------------------------------------------
- 运行结果:
- 原对象obj: [1, 2, 3] 2723109220736
- 浅拷贝对象b: [1, 2, 3] 2723109272512
分析运行结果可知,对于可变对象,浅拷贝对象b的内存地址和原对象obj的内存地址不一致,浅拷贝开辟了新的内存地址。
(1)如果对象obj发生改变,浅拷贝对象b会发生怎样的变化?
- import copy
-
- # 可变对象
- obj = [1, 2, 3]
- b = copy.copy(obj)
-
- print("原对象obj:", obj, id(obj))
- print("浅拷贝对象b:", b, id(b))
-
- print("修改对象obj后:")
- obj.append(4)
- print("原对象obj:", obj, id(obj))
- print("浅拷贝对象b:", b, id(b))
-
- ----------------------------------------------------------------------------
- 运行结果:
- 原对象obj: [1, 2, 3] 2065559531904
- 浅拷贝对象b: [1, 2, 3] 2065559583680
- 修改对象obj后:
- 原对象obj: [1, 2, 3, 4] 2065559531904
- 浅拷贝对象b: [1, 2, 3] 2065559583680
分析运行结果可知,原对象obj的值发生改变后,浅拷贝对象b的值和内存地址并不会受到影像。
(2)如果可变对象obj是一个嵌套结构呢?
- import copy
-
- # 可变对象,嵌套结构
- obj1 = [1, 2]
- obj = [1, 2, 3, obj1]
- b = copy.copy(obj)
-
- print("原对象obj:", obj, id(obj))
- print("浅拷贝对象b:", b, id(b))
-
- print("修改父对象obj,子对象obj1后:")
- obj1.append(3)
- obj[0] = 'a'
- print("原对象obj:", obj, id(obj))
- print("浅拷贝对象b:", b, id(b))
-
- -------------------------------------------------
- 运行结果:
- 原对象obj: [1, 2, 3, [1, 2]] 2545761713280
- 浅拷贝对象b: [1, 2, 3, [1, 2]] 2545761711744
- 修改父对象obj,子对象obj1后:
- 原对象obj: ['a', 2, 3, [1, 2, 3]] 2545761713280
- 浅拷贝对象b: [1, 2, 3, [1, 2, 3]] 2545761711744
分析运行结果可知,对于包含了嵌套结构的可变对象。
父对象obj发生改变后,浅拷贝对象b不会受到影响,值和内存地址都不变。
子对象obj1发生改变后,浅拷贝对象b的子元素[1,2]也跟着变成了[1,2,3],内存地址不变。
小结:
对于可变对象,浅拷贝只拷贝父对象,开辟新的内存地址。不拷贝子对象,只是引用了子对象。
- import copy
-
- # 不可变对象
- obj = (1, 2, 3)
- b = copy.copy(obj)
-
- print("原对象obj:", obj, id(obj))
- print("浅拷贝对象b:", b, id(b))
-
- ----------------------------------------------------------------------------------
- 运行结果:
- 原对象obj: (1, 2, 3) 2442259410880
- 浅拷贝对象b: (1, 2, 3) 2442259410880
分析运行结果可知,对于不可变对象,浅拷贝只是地址的引用,并不会开辟新的内存地址。
- import copy
-
- # 可变对象
- obj = [1, 2, 3]
- c = copy.deepcopy(obj)
-
- print("原对象obj:", obj, id(obj))
- print("深拷贝对象c:", c, id(c))
-
- ------------------------------------------------------------------------
- 运行结果:
-
- 原对象obj: [1, 2, 3] 2616267190656
- 深拷贝对象c: [1, 2, 3] 2616267242368
分析运行结果可知,对于可变对象,深拷贝会开辟新的内存地址。
(1))如果对象obj发生改变,深拷贝对象c会发生怎样的变化?
- import copy
-
- # 可变对象
- obj = [1, 2, 3]
- c = copy.deepcopy(obj)
-
- print("原对象obj:", obj, id(obj))
- print("深拷贝对象c:", c, id(c))
-
- print("修改原对象obj后:")
- obj[0] = 'a'
- print("原对象obj:", obj, id(obj))
- print("深拷贝对象c:", c, id(c))
-
- ----------------------------------------------------------------------------
- 运行结果:
- 原对象obj: [1, 2, 3] 2451928592704
- 深拷贝对象c: [1, 2, 3] 2451928644480
- 修改原对象obj后:
- 原对象obj: ['a', 2, 3] 2451928592704
- 深拷贝对象c: [1, 2, 3] 2451928644480
分析运行结果可知,原对象obj的值发生改变后,深拷贝对象的值和内存地址并不会受到影像。
(2)如果可变对象obj是一个嵌套结构呢?
- import copy
-
- # 可变对象
- obj1 = [1,2]
- obj = [1, 2, 3,obj1]
- c = copy.deepcopy(obj)
-
- print("原对象obj:", obj, id(obj))
- print("深拷贝对象c:", c, id(c))
-
- print("修改父对象obj,子对象obj1后:")
- obj1.append(3)
- obj[0] = 'a'
- print("原对象obj:", obj, id(obj))
- print("深拷贝对象c:", c, id(c))
-
- --------------------------------------------------------------------------
- 运行结果:
- 原对象obj: [1, 2, 3, [1, 2]] 1690664172288
- 深拷贝对象c: [1, 2, 3, [1, 2]] 1690664170816
- 修改父对象obj,子对象obj1后:
- 原对象obj: ['a', 2, 3, [1, 2, 3]] 1690664172288
- 深拷贝对象c: [1, 2, 3, [1, 2]] 1690664170816
分析运行结果可知,对于包含了嵌套结构的可变对象。
父对象obj发生改变后,深拷贝对象c不会受到影响,值和内存地址都不变。
子对象obj1发生改变后,深拷贝对象c不会受到影响,值和内存地址都不变。
小结:
对于可变对象,深拷贝会拷贝父对象和所有的子对象,开辟新的内存地址。
- import copy
-
- # 不可变对象
-
- obj = (1,2,3)
- c = copy.deepcopy(obj)
-
- print("原对象obj:", obj, id(obj))
- print("深拷贝对象c:", c, id(c))
-
- ------------------------------------------------------------------------------
- 运行结果:
- 原对象obj: (1, 2, 3) 2928533385024
- 深拷贝对象c: (1, 2, 3) 2928533385024
分析运行结果可知,对于不可变对象,深拷贝只是地址的引用,并不会开辟新的内存地址。
赋值:
赋值只是创建了一个原对象的引用对象,并不会开辟新的内存地址。
原对象发生改变,赋值对象的值也会同步变化,内存地址不变。
浅拷贝:
对于可变对象,浅拷贝只拷贝父对象,开辟新的内存地址。不拷贝子对象,只是引用了子对象。
对于不可变对象,浅拷贝只是地址的引用,并不会开辟新的内存地址。
深拷贝:
对于可变对象,深拷贝会拷贝父对象和所有的子对象,开辟新的内存地址。
对于不可变对象,深拷贝只是地址的引用,并不会开辟新的内存地址。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。