『python3』可变与不可变,浅拷贝与深拷贝

2024-04-15 10:26:56 浏览数 (3)

1.可变与不可变数据类型

1.1 immutable:

不可变数据类型指的是一旦创建,其值就不能被改变的数据类型。在Python中,常见的不可变数据类型包括:

  • int(整数)
  • float(浮点数)
  • complex(复数)
  • str(字符串)
  • tuple(元组)

示例:

代码语言:javascript复制
if __name__ == '__main__':
    age = 25
    print(age, id(age))
    num = age
    print(id(num), id(age))
    num = 30
    print(f'immutable: {age=} {num=} id(age)={id(age)} id(num)={id(num)}')
--------------------------------
25 140713717812408
# age 和 num 的地址相同
140713717812408 140713717812408 
# num重新赋值后 num的地址变了 age的值没变地址没变
immutable: age=25 num=30 id(age)=140713717812408 id(num)=140713717812568

总结:数据类型的值变了,内存地址也变了,这种数据类型为不可变。

1.2 mutable

可变数据类型允许你在创建后修改其值。Python中的可变数据类型包括:

  • list(列表)
  • dict(字典)
  • set(集合)
  • bytearray(字节数组)

示例:

代码语言:javascript复制
if __name__ == '__main__':
    列表 = ['北京', '上海', '深圳', '广州']
    print(f'origin 列表 {列表} id(列表) = {id(列表)}')
    列表.append('太原')
    print(f'modified 列表 {列表} id(列表) = {id(列表)}')
--------------------------------
origin 列表 ['北京', '上海', '深圳', '广州'] id(列表) = 2449677930880
modified 列表 ['北京', '上海', '深圳', '广州', '太原'] id(列表) = 2449677930880

总结:数据类型的值变了,内存地址没变,这种数据类型为可变。

2. 浅拷贝与深拷贝

2.1 shallow copy:

在Python中,你可以使用copy模块的copy()函数或切片操作来实现浅拷贝。拷贝后的对象与源对象是两个独立的对象,如果源对象中包含可变对象,浅拷贝只拷贝可变对象的引用而非可变对象本身,所以修改可变对象会同时作用于源对象和拷贝后对象。

示例:

代码语言:javascript复制
import copy

if __name__ == '__main__':
    省 = ['山西', '河北', '河南', '山东', '吉林', '一线']
    市 = ['太原', '石家庄', '郑州', '济南', '长春', []]
    字典 = dict(zip(省, 市))
    print(字典)
    temp = copy.copy(字典)
    temp['宁夏'] = '银川'
    print(temp, 字典, id(temp), id(字典), sep='n')
    temp['一线'].append('北京')
    print(temp, 字典, id(temp), id(字典), sep='n')
--------------------------------
{'山西': '太原', '河北': '石家庄', '河南': '郑州', '山东': '济南', '吉林': '长春', '一线': []}
// 对字典自身(非可变对象)修改是独立的
{'山西': '太原', '河北': '石家庄', '河南': '郑州', '山东': '济南', '吉林': '长春', '一线': [], '宁夏': '银川'}
{'山西': '太原', '河北': '石家庄', '河南': '郑州', '山东': '济南', '吉林': '长春', '一线': []}
// 地址是独立的
2173107763712
2173111155520
// 字典中可变对象一线的改变 同时作用与源对象与拷贝对象
{'山西': '太原', '河北': '石家庄', '河南': '郑州', '山东': '济南', '吉林': '长春', '一线': ['北京'], '宁夏': '银川'}
{'山西': '太原', '河北': '石家庄', '河南': '郑州', '山东': '济南', '吉林': '长春', '一线': ['北京']}
2173107763712
2173111155520

总结:浅拷贝对象中的可变对象是共享引用

2.2 deep copy

在Python中,你可以使用copy模块的deepcopy()函数来实现深拷贝。这个对象及其所有子对象都是完全独立的,与原始对象没有任何共享。

示例:

代码语言:javascript复制
deep = copy.deepcopy(字典)
print(deep)
字典['一线'].append('上海')
deep['一线'].append('深圳')
print(f'字典: {字典} ndeep: {deep} n id(字典)={id(字典)} id(deep)={id(deep)}')
--------------------------------
{'山西': '太原', '河北': '石家庄', '河南': '郑州', '山东': '济南', '吉林': '长春', '一线': ['北京']}
字典: {'山西': '太原', '河北': '石家庄', '河南': '郑州', '山东': '济南', '吉林': '长春', '一线': ['北京', '上海']} 
deep: {'山西': '太原', '河北': '石家庄', '河南': '郑州', '山东': '济南', '吉林': '长春', '一线': ['北京', '深圳']} 
id(字典)=2334986648384 id(deep)=2334986646784

总结:深拷贝对象中的可变对象是独立引用

0 人点赞