当前位置:   article > 正文

python基础 — 赋值,浅拷贝,深拷贝_赋值 深拷贝和浅拷贝 python

赋值 深拷贝和浅拷贝 python

一、可变对象和不可变对象

先来了解两个重要的概念:

  • 可变对象:对象的值发生变化,内存地址不变。常见的有list, set, dict
  • 不可变对象:对象的值发生变化,内存地址改变。常见的有int, float,string,tuple

为了弄明白赋值,浅拷贝,深拷贝的差异,下面将通过实例来分析。

二、赋值

1、 可变对象

  1. # 可变对象
  2. obj = [1, 2, 3]
  3. a = obj
  4. print("原对象obj:", obj, id(obj))
  5. print("赋值对象a:", a, id(a))
  6. ------------------------------------------------------------------------
  7. 运行结果:
  8. 原对象obj: [1, 2, 3] 2211245785600
  9. 赋值对象a: [1, 2, 3] 2211245785600

分析运行结果可知,赋值对象a跟原对象obj的值相同,内存地址相同。

(1)如果对象obj发生改变,赋值的对象a会发生怎样的变化?

  1. # 可变对象
  2. obj = [1, 2, 3]
  3. a = obj
  4. print("原对象obj:", obj, id(obj))
  5. print("赋值对象a:", a, id(a))
  6. print("修改对象obj后:")
  7. obj.append(4)
  8. print("原对象obj:", obj, id(obj))
  9. print("赋值对象a:", a, id(a))
  10. ------------------------------------------------------------------------------
  11. 运行结果:
  12. 原对象obj: [1, 2, 3] 1896687337984
  13. 赋值对象a: [1, 2, 3] 1896687337984
  14. 修改对象obj后:
  15. 原对象obj: [1, 2, 3, 4] 1896687337984
  16. 赋值对象a: [1, 2, 3, 4] 1896687337984

分析运行结果可知,原对象obj的值发生改变后,赋值对象a的值也跟着改变了,但是他们的内存地址并不会改变。

2、不可变对象

  1. # 不可变对象
  2. obj = (1, 2, 3)
  3. a = obj
  4. print("原对象obj:", obj, id(obj))
  5. print("赋值对象a:", a, id(a))
  6. ---------------------------------------------------------------------------------
  7. 运行结果:
  8. 原对象obj: (1, 2, 3) 2408442060864
  9. 赋值对象a: (1, 2, 3) 2408442060864

分析运行结果可知,赋值对象a跟原对象obj的值相同,内存地址相同。

小结:

赋值只是创建了一个原对象的引用对象,并不会开辟新的内存地址。

原对象发生改变,赋值对象的值也会同步变化,内存地址不变。

 

三、浅拷贝(copy)

1、可变对象

  1. import copy
  2. # 可变对象
  3. obj = [1, 2, 3]
  4. b = copy.copy(obj)
  5. print("原对象obj:", obj, id(obj))
  6. print("浅拷贝对象b:", b, id(b))
  7. ------------------------------------------------------------------------------------
  8. 运行结果:
  9. 原对象obj: [1, 2, 3] 2723109220736
  10. 浅拷贝对象b: [1, 2, 3] 2723109272512

分析运行结果可知,对于可变对象,浅拷贝对象b的内存地址和原对象obj的内存地址不一致,浅拷贝开辟了新的内存地址。

(1)如果对象obj发生改变,浅拷贝对象b会发生怎样的变化?

  1. import copy
  2. # 可变对象
  3. obj = [1, 2, 3]
  4. b = copy.copy(obj)
  5. print("原对象obj:", obj, id(obj))
  6. print("浅拷贝对象b:", b, id(b))
  7. print("修改对象obj后:")
  8. obj.append(4)
  9. print("原对象obj:", obj, id(obj))
  10. print("浅拷贝对象b:", b, id(b))
  11. ----------------------------------------------------------------------------
  12. 运行结果:
  13. 原对象obj: [1, 2, 3] 2065559531904
  14. 浅拷贝对象b: [1, 2, 3] 2065559583680
  15. 修改对象obj后:
  16. 原对象obj: [1, 2, 3, 4] 2065559531904
  17. 浅拷贝对象b: [1, 2, 3] 2065559583680

分析运行结果可知,原对象obj的值发生改变后,浅拷贝对象b的值和内存地址并不会受到影像。

(2)如果可变对象obj是一个嵌套结构呢?

  1. import copy
  2. # 可变对象,嵌套结构
  3. obj1 = [1, 2]
  4. obj = [1, 2, 3, obj1]
  5. b = copy.copy(obj)
  6. print("原对象obj:", obj, id(obj))
  7. print("浅拷贝对象b:", b, id(b))
  8. print("修改父对象obj,子对象obj1后:")
  9. obj1.append(3)
  10. obj[0] = 'a'
  11. print("原对象obj:", obj, id(obj))
  12. print("浅拷贝对象b:", b, id(b))
  13. -------------------------------------------------
  14. 运行结果:
  15. 原对象obj: [1, 2, 3, [1, 2]] 2545761713280
  16. 浅拷贝对象b: [1, 2, 3, [1, 2]] 2545761711744
  17. 修改父对象obj,子对象obj1后:
  18. 原对象obj: ['a', 2, 3, [1, 2, 3]] 2545761713280
  19. 浅拷贝对象b: [1, 2, 3, [1, 2, 3]] 2545761711744

分析运行结果可知,对于包含了嵌套结构的可变对象。

父对象obj发生改变后,浅拷贝对象b不会受到影响,值和内存地址都不变。

子对象obj1发生改变后,浅拷贝对象b的子元素[1,2]也跟着变成了[1,2,3],内存地址不变。

小结:

对于可变对象,浅拷贝只拷贝父对象,开辟新的内存地址。不拷贝子对象,只是引用了子对象。

2、不可变对象

  1. import copy
  2. # 不可变对象
  3. obj = (1, 2, 3)
  4. b = copy.copy(obj)
  5. print("原对象obj:", obj, id(obj))
  6. print("浅拷贝对象b:", b, id(b))
  7. ----------------------------------------------------------------------------------
  8. 运行结果:
  9. 原对象obj: (1, 2, 3) 2442259410880
  10. 浅拷贝对象b: (1, 2, 3) 2442259410880

分析运行结果可知,对于不可变对象,浅拷贝只是地址的引用,并不会开辟新的内存地址。

四、深拷贝(deepcopy)

1、可变对象

  1. import copy
  2. # 可变对象
  3. obj = [1, 2, 3]
  4. c = copy.deepcopy(obj)
  5. print("原对象obj:", obj, id(obj))
  6. print("深拷贝对象c:", c, id(c))
  7. ------------------------------------------------------------------------
  8. 运行结果:
  9. 原对象obj: [1, 2, 3] 2616267190656
  10. 深拷贝对象c: [1, 2, 3] 2616267242368

分析运行结果可知,对于可变对象,深拷贝会开辟新的内存地址。

(1))如果对象obj发生改变,深拷贝对象c会发生怎样的变化?

  1. import copy
  2. # 可变对象
  3. obj = [1, 2, 3]
  4. c = copy.deepcopy(obj)
  5. print("原对象obj:", obj, id(obj))
  6. print("深拷贝对象c:", c, id(c))
  7. print("修改原对象obj后:")
  8. obj[0] = 'a'
  9. print("原对象obj:", obj, id(obj))
  10. print("深拷贝对象c:", c, id(c))
  11. ----------------------------------------------------------------------------
  12. 运行结果:
  13. 原对象obj: [1, 2, 3] 2451928592704
  14. 深拷贝对象c: [1, 2, 3] 2451928644480
  15. 修改原对象obj后:
  16. 原对象obj: ['a', 2, 3] 2451928592704
  17. 深拷贝对象c: [1, 2, 3] 2451928644480

分析运行结果可知,原对象obj的值发生改变后,深拷贝对象的值和内存地址并不会受到影像。

(2)如果可变对象obj是一个嵌套结构呢?

  1. import copy
  2. # 可变对象
  3. obj1 = [1,2]
  4. obj = [1, 2, 3,obj1]
  5. c = copy.deepcopy(obj)
  6. print("原对象obj:", obj, id(obj))
  7. print("深拷贝对象c:", c, id(c))
  8. print("修改父对象obj,子对象obj1后:")
  9. obj1.append(3)
  10. obj[0] = 'a'
  11. print("原对象obj:", obj, id(obj))
  12. print("深拷贝对象c:", c, id(c))
  13. --------------------------------------------------------------------------
  14. 运行结果:
  15. 原对象obj: [1, 2, 3, [1, 2]] 1690664172288
  16. 深拷贝对象c: [1, 2, 3, [1, 2]] 1690664170816
  17. 修改父对象obj,子对象obj1后:
  18. 原对象obj: ['a', 2, 3, [1, 2, 3]] 1690664172288
  19. 深拷贝对象c: [1, 2, 3, [1, 2]] 1690664170816

分析运行结果可知,对于包含了嵌套结构的可变对象。

父对象obj发生改变后,深拷贝对象c不会受到影响,值和内存地址都不变。

子对象obj1发生改变后,深拷贝对象c不会受到影响,值和内存地址都不变。

小结:

对于可变对象,深拷贝会拷贝父对象和所有的子对象,开辟新的内存地址。

2、不可变对象

  1. import copy
  2. # 不可变对象
  3. obj = (1,2,3)
  4. c = copy.deepcopy(obj)
  5. print("原对象obj:", obj, id(obj))
  6. print("深拷贝对象c:", c, id(c))
  7. ------------------------------------------------------------------------------
  8. 运行结果:
  9. 原对象obj: (1, 2, 3) 2928533385024
  10. 深拷贝对象c: (1, 2, 3) 2928533385024

分析运行结果可知,对于不可变对象,深拷贝只是地址的引用,并不会开辟新的内存地址。

五、总结

赋值:

赋值只是创建了一个原对象的引用对象,并不会开辟新的内存地址。

原对象发生改变,赋值对象的值也会同步变化,内存地址不变。

浅拷贝:

对于可变对象,浅拷贝只拷贝父对象,开辟新的内存地址。不拷贝子对象,只是引用了子对象。

对于不可变对象,浅拷贝只是地址的引用,并不会开辟新的内存地址。

深拷贝:

对于可变对象,深拷贝会拷贝父对象和所有的子对象,开辟新的内存地址。

对于不可变对象,深拷贝只是地址的引用,并不会开辟新的内存地址。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小丑西瓜9/article/detail/71410
推荐阅读
相关标签
  

闽ICP备14008679号