|
马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
本帖最后由 Free_num 于 2023-8-30 16:19 编辑
可变/不可变/浅拷贝
- '''
- <font size="3" color="#ff8c00">可变类型</font>:数据可直接进行修改且id不变化---------->证明修改的是原值
- <font color="#ff8c00" size="3">不可变类型</font>:值改变,id也变---------->原值不能被修改
- 二者可以通过ID来区分
- 可变类型:列表、字典、集合
- 不可变类型:字符串、元组、数据类型
- 元组被称为制度列表,即数据可以被查询,但是不能被修改,
- '''
- '''
- li = [1, 2]
- t = (1, 't', li)
- print(f'修改元组中的列表前:{t}', id(t))
- # 修改元组中的列表前:(1, 't', [1, 2]) 1931246079296
- li[0] = 'Serena'
- print(f'修改元组中的列表后:{t}', id(t))
- # 修改元组中的列表后:(1, 't', ['Serena', 2]) 1931246079296
- 上面结果中,虽然元组数据发生了变化,但是id却未发生变化,那是因为元组中的列表是可变类型,列表的数据发生了变化,
- 但列表在元组中的地址的值没有发生变化
- 因此,元组的地址没有发生变化
- '''
- '''
- <font size="3" color="#ff8c00">赋值:</font>如果是 <u><i>可变类型数据</i></u>,赋值对象随着源对象的改变而改变,二者指向的是同一个内存地址
- 如果是 <u><i>不可变类型数据</i></u>,没有影响
- '''
- <span style="background-color: mediumturquoise;"># 可变类型数据</span>
- li1 = [1, 3, 5, [3]]
- li2 = li1
- print(f'源列表修改前li1:{li1}', id(li1))
- print(f'源列表修改前li2:{li2}', id(li2))
- li1[3][0] = 's'
- print(f'源列表修改后li1:{li1}', id(li1))
- print(f'源列表修改后li2:{li2}', id(li2))
- li2[3][0] = 123
- print(f'li2列表修改后li1:{li1}', id(li1))
- print(f'li2列表修改后li2:{li2}', id(li2))
- '''
- 以上的id值均相同----->赋值是可变类型数据,内存地址是同一个,所以无论改变的是源对象还是赋值对象,id都一样
- '''
- <span style="background-color: mediumturquoise;"># 不可变类型数据</span>
- a = 7
- b = a
- print(id(a),'\t', id(b)) # 2023961330096 2023961330096
- # 对源对象进行修改
- a = 's'
- print(id(a), '\t', id(b)) # 2023962151920 2023961330096 ------> 没有影响
-
- <span style="background-color: mediumturquoise;"><font size="4"># 深、浅拷贝,使用时需要导包 import copy</font></span>
- '''
- <font size="3" color="#ff8c00"> 浅拷贝:</font>创建一个新对象,引用的是源对象的子对象---------内层地址不会改变,外层数据地址改不改变看外层数据类型
- 使用:copy.copy()
- '''
- import copy
- <span style="background-color: mediumturquoise;"><font size="3"># 外层可变,内层可变</font></span>
- l = [1, 3, 5, {'q', 'o^0'}]
- l1 = copy.copy(l)
- print('源对象外层数据地址:', l, id(l)) # 1589324513344
- print('浅拷贝后的外层数据地址:', l1, id(l1)) # 1589324494400 外层地址改变
- print('--------- 内层 ----------')
- print('源对象内层数据地址:', id(l[3])) # 1589324258144
- print('浅拷贝后的内层数据地址:', id(l[3])) # 1589324258144 内层地址不变
- print('-------------------')
- l.append('¥')
- print('外层修改后源对象:', l) # [1, 3, 5, {'o^0', 'q'}, '¥']
- print('外层修改后的浅拷贝:', l1) # [1, 3, 5, {'o^0', 'q'}]
- print('-------------------') # 外层内存地址不同,数据不会产生影响,外层数据是独立的
- l[3].remove('q')
- print('内层数据修改后源对象:', l) # [1, 3, 5, {'o^0'}, '¥']
- print('内层数据修改后的浅拷贝:', l1) # [1, 3, 5, {'o^0'}]
- print('-------------------')
- <span style="background-color: wheat;">'''
- 引用的是源对象的子对象,所以内层内存地址相同,
- 由于内层是可变类型,可变类型数据发生变化时,id不变,因此当内层数据发生变化时,用的还是原来的内存地址,
- 故当内层发生变化时,浅拷贝对象的内层也发生相同的变化
- '''</span>
- <span style="background-color: mediumturquoise;"><font size="3"># 外层可变,内层不可变</font></span>
- l2 = [2, 3, ('s', 'r')]
- l3 = copy.copy(l2)
- print('源对象外层数据地址', l2, id(l2)) # [2, 3, ('s', 'r')] 1589324494144
- print('浅拷贝后的外层数据地址:', l3, id(l3)) # [2, 3, ('s', 'r')] 1589324495104 外层地址改变
- print('--------- 内层 ----------')
- print('源对象内层数据地址:', id(l2[2])) # 1589322737344
- print('浅拷贝后的内层数据地址:', id(l2[2])) # 1589322737344 内层地址不变
- print('-------------------')
- l2.insert(1, 'e')
- print('外层修改后源对象:', l2) # [2, 'e', 3, ('s', 'r')]
- print('外层修改后的浅拷贝:', l3) # [2, 3, ('s', 'r')] 原因同上,外层数据资源独立
- print('-------------------')
- l2[-1] += (60,)
- print('内层数据修改后源对象:', l2) # [2, 'e', 3, ('s', 'r', 60)]
- print('内层数据修改后的浅拷贝:', l3) # [2, 3, ('s', 'r')]
- print('-------------------')
- <span style="background-color: wheat;">'''
- 引用的是源对象的子对象,所以内层内存地址相同,
- 由于内层数据是不可变类型,当内层数据发生变化时,id发生变化,
- 而浅拷贝引用的是改变之前的内存空间,
- 故当内存数据发生改变时,浅拷贝的对象未发生变化
- '''</span>
- <span style="background-color: mediumturquoise;"><font size="3"># 外层不可变,内层可变</font></span>
- l4 = [1, 3, 5]
- t = ('er', 4, l4)
- t1 = copy.copy(t)
- print('源对象外层数据地址', t, id(t)) # 1589324527488
- print('浅拷贝后的外层数据地址', t1, id(t1)) # 1589324527488 外层地址未发生变化
- print('--------- 内层 ----------')
- print('源对象内层数据地址', id(l4)) # 1589324493440
- print('浅拷贝后的内层数据地址', id(t1[-1])) # 1589324493440 内层地址不变
- print('-------------------')
- t += (90,)
- print('外层数据修改后源对象:', t) # ('er', 4, [1, 3, 5], 90)
- print('外层数据修改后的浅拷贝:', t1) # ('er', 4, [1, 3, 5])
- print('-------------------')
- l4.append('WE')
- print('内层数据修改后源对象:', t) # ('er', 4, [1, 3, 5, 'WE'], 90)
- print('内层数据修改后的浅拷贝:', t1) # ('er', 4, [1, 3, 5, 'WE'])
- <font size="3" style="background-color: mediumturquoise;"># 外层不可变,内层不可变</font>
- '''
- 这个就先不举例子啦
- 综上所述:
- 浅拷贝内层数据内存地址不会发生改变
- 外层数据是可变类型-----会改变
- 是不可变类型-----不会改变
- '''
复制代码
|
|