鱼C论坛

 找回密码
 立即注册
查看: 1008|回复: 1

[学习笔记] Python 可变/不可变/浅拷贝

[复制链接]
发表于 2023-8-30 16:10:35 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 Free_num 于 2023-8-30 16:19 编辑

可变/不可变/浅拷贝

  1. '''
  2. <font size="3" color="#ff8c00">可变类型</font>:数据可直接进行修改且id不变化---------->证明修改的是原值
  3. <font color="#ff8c00" size="3">不可变类型</font>:值改变,id也变---------->原值不能被修改

  4. 二者可以通过ID来区分
  5. 可变类型:列表、字典、集合
  6. 不可变类型:字符串、元组、数据类型

  7. 元组被称为制度列表,即数据可以被查询,但是不能被修改,
  8. '''

  9. '''
  10. li = [1, 2]
  11. t = (1, 't', li)
  12. print(f'修改元组中的列表前:{t}', id(t))
  13. # 修改元组中的列表前:(1, 't', [1, 2]) 1931246079296
  14. li[0] = 'Serena'
  15. print(f'修改元组中的列表后:{t}', id(t))
  16. # 修改元组中的列表后:(1, 't', ['Serena', 2]) 1931246079296


  17. 上面结果中,虽然元组数据发生了变化,但是id却未发生变化,那是因为元组中的列表是可变类型,列表的数据发生了变化,
  18. 但列表在元组中的地址的值没有发生变化
  19. 因此,元组的地址没有发生变化
  20. '''



  21. '''
  22. <font size="3" color="#ff8c00">赋值:</font>如果是  <u><i>可变类型数据</i></u>,赋值对象随着源对象的改变而改变,二者指向的是同一个内存地址
  23.            如果是  <u><i>不可变类型数据</i></u>,没有影响
  24. '''
  25. <span style="background-color: mediumturquoise;"># 可变类型数据</span>
  26. li1 = [1, 3, 5, [3]]
  27. li2 = li1
  28. print(f'源列表修改前li1:{li1}', id(li1))
  29. print(f'源列表修改前li2:{li2}', id(li2))

  30. li1[3][0] = 's'
  31. print(f'源列表修改后li1:{li1}', id(li1))
  32. print(f'源列表修改后li2:{li2}', id(li2))

  33. li2[3][0] = 123
  34. print(f'li2列表修改后li1:{li1}', id(li1))
  35. print(f'li2列表修改后li2:{li2}', id(li2))
  36. '''
  37. 以上的id值均相同----->赋值是可变类型数据,内存地址是同一个,所以无论改变的是源对象还是赋值对象,id都一样
  38. '''

  39. <span style="background-color: mediumturquoise;"># 不可变类型数据</span>
  40. a = 7
  41. b = a
  42. print(id(a),'\t', id(b))    # 2023961330096          2023961330096
  43. # 对源对象进行修改
  44. a = 's'
  45. print(id(a), '\t', id(b))   # 2023962151920          2023961330096 ------> 没有影响



  46. <span style="background-color: mediumturquoise;"><font size="4"># 深、浅拷贝,使用时需要导包 import copy</font></span>
  47. '''
  48. <font size="3" color="#ff8c00"> 浅拷贝:</font>创建一个新对象,引用的是源对象的子对象---------内层地址不会改变,外层数据地址改不改变看外层数据类型
  49. 使用:copy.copy()
  50. '''
  51. import copy
  52. <span style="background-color: mediumturquoise;"><font size="3"># 外层可变,内层可变</font></span>
  53. l = [1, 3, 5, {'q', 'o^0'}]
  54. l1 = copy.copy(l)
  55. print('源对象外层数据地址:', l, id(l))                                      # 1589324513344
  56. print('浅拷贝后的外层数据地址:', l1, id(l1))                           # 1589324494400  外层地址改变
  57. print('--------- 内层 ----------')
  58. print('源对象内层数据地址:', id(l[3]))                                 # 1589324258144
  59. print('浅拷贝后的内层数据地址:', id(l[3]))                         #  1589324258144  内层地址不变
  60. print('-------------------')
  61. l.append('¥')
  62. print('外层修改后源对象:', l)                                      # [1, 3, 5, {'o^0', 'q'}, '¥']
  63. print('外层修改后的浅拷贝:', l1)                                 # [1, 3, 5, {'o^0', 'q'}]
  64. print('-------------------')                                               # 外层内存地址不同,数据不会产生影响,外层数据是独立的
  65. l[3].remove('q')
  66. print('内层数据修改后源对象:', l)                              # [1, 3, 5, {'o^0'}, '¥']
  67. print('内层数据修改后的浅拷贝:', l1)                         # [1, 3, 5, {'o^0'}]
  68. print('-------------------')
  69. <span style="background-color: wheat;">'''
  70. 引用的是源对象的子对象,所以内层内存地址相同,
  71. 由于内层是可变类型,可变类型数据发生变化时,id不变,因此当内层数据发生变化时,用的还是原来的内存地址,
  72. 故当内层发生变化时,浅拷贝对象的内层也发生相同的变化
  73. '''</span>

  74. <span style="background-color: mediumturquoise;"><font size="3"># 外层可变,内层不可变</font></span>
  75. l2 = [2, 3, ('s', 'r')]
  76. l3 = copy.copy(l2)
  77. print('源对象外层数据地址', l2, id(l2))                                  # [2, 3, ('s', 'r')] 1589324494144
  78. print('浅拷贝后的外层数据地址:', l3, id(l3))                        # [2, 3, ('s', 'r')] 1589324495104  外层地址改变
  79. print('--------- 内层 ----------')
  80. print('源对象内层数据地址:', id(l2[2]))                              # 1589322737344
  81. print('浅拷贝后的内层数据地址:', id(l2[2]))                       # 1589322737344     内层地址不变
  82. print('-------------------')
  83. l2.insert(1, 'e')
  84. print('外层修改后源对象:', l2)                                          # [2, 'e', 3, ('s', 'r')]
  85. print('外层修改后的浅拷贝:', l3)                                      # [2, 3, ('s', 'r')]       原因同上,外层数据资源独立
  86. print('-------------------')
  87. l2[-1] += (60,)
  88. print('内层数据修改后源对象:', l2)                                 # [2, 'e', 3, ('s', 'r', 60)]
  89. print('内层数据修改后的浅拷贝:', l3)                              # [2, 3, ('s', 'r')]
  90. print('-------------------')
  91. <span style="background-color: wheat;">'''
  92. 引用的是源对象的子对象,所以内层内存地址相同,
  93. 由于内层数据是不可变类型,当内层数据发生变化时,id发生变化,
  94. 而浅拷贝引用的是改变之前的内存空间,
  95. 故当内存数据发生改变时,浅拷贝的对象未发生变化
  96. '''</span>


  97. <span style="background-color: mediumturquoise;"><font size="3"># 外层不可变,内层可变</font></span>
  98. l4 = [1, 3, 5]
  99. t = ('er', 4, l4)
  100. t1 = copy.copy(t)
  101. print('源对象外层数据地址', t, id(t))                # 1589324527488
  102. print('浅拷贝后的外层数据地址', t1, id(t1))           # 1589324527488    外层地址未发生变化
  103. print('--------- 内层 ----------')
  104. print('源对象内层数据地址', id(l4))                  # 1589324493440
  105. print('浅拷贝后的内层数据地址', id(t1[-1]))           # 1589324493440    内层地址不变
  106. print('-------------------')
  107. t += (90,)
  108. print('外层数据修改后源对象:', t)             # ('er', 4, [1, 3, 5], 90)
  109. print('外层数据修改后的浅拷贝:', t1)          # ('er', 4, [1, 3, 5])
  110. print('-------------------')
  111. l4.append('WE')
  112. print('内层数据修改后源对象:', t)             # ('er', 4, [1, 3, 5, 'WE'], 90)
  113. print('内层数据修改后的浅拷贝:', t1)           # ('er', 4, [1, 3, 5, 'WE'])

  114. <font size="3" style="background-color: mediumturquoise;"># 外层不可变,内层不可变</font>
  115. '''
  116. 这个就先不举例子啦

  117. 综上所述:
  118. 浅拷贝内层数据内存地址不会发生改变
  119. 外层数据是可变类型-----会改变
  120.         是不可变类型-----不会改变
  121. '''
复制代码


本帖被以下淘专辑推荐:

小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

头像被屏蔽
发表于 2023-9-8 11:51:18 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-6-9 12:26

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表