python可变元素list在程序中的注意事项

1 list的可变性

在python程序中,列表list的存贮方式与int的存贮方式是不同的,换句话说,python中可变类型的存储方式与不可变类型的存储方式是不同的。

例如,对于单一的元素,有如下操作时:

a = 1
b = a
b = 5
print(a, b)
print(id(a),id(b))  # 打印两个变量的地址

输出>> 1 5
>> 140731421349024 140731421348896
即对整型变量的赋值相当于一个真正的复制过程,两个变量有了两个不同的内存地址,其实是因为第3句把第二句覆盖掉了。

而对列表元素进行赋值时:

a = [[0,1,2],2,3]
b = a
b[0] = 100
print(a, b)
print(id(a),id(b))  # 打印两个变量的地址

输出>> [100, 2, 3] [100, 2, 3]
>> 2847777749608 2847777749608
也就是说列表的赋值本质上是名称多了一个,换句话说,就是列表的名字多了一个,列表还是原来那个列表。两个变量具有相同的内存地址。

下面看一下.copy()方法:

a = [1,2,3]
b = a.copy()
b[0] = 100
print(a, b)
print(id(a),id(b))  # 打印两个变量的地址

输出:>> [1, 2, 3] [100, 2, 3]
>> 2744646268360 2744646268744
看起来问题得到了解决,两个变量内存地址也不一样了,然而.cpoy()都叫它浅拷贝,原因在于如下所示:

a = [[0,1,2],2,3]
b = a.copy()
b[0][1] = 100
print(a, b)
print(id(a),id(b))  # 打印两个变量的地址
print(id(a[0]), id(b[0]))  # 打印两个变量中变量的地址

输出:>> [[[0, 100, 2], 2, 3] [[0, 100, 2], 2, 3]
>> 2649294660232 2649295880648
>> 2649294660168 2649294660168
可以看到,.copy()方法只是将第一层列表的元素完全拷贝了一份新的内存,再多一层的列表就没有拷贝了,因此称它为浅拷贝。
当列表只有一维时,是可以使用浅拷贝的。
深拷贝:

import copy
a = [[0,1,2],2,3]
b = copy.deepcopy(a)
b[0][1] = 100
print(a, b)
print(id(a),id(b))  # 打印两个变量的地址
print(id(a[0]), id(b[0]))  # 打印两个变量中变量的地址

输出:>> [[0, 1, 2], 2, 3] [[0, 100, 2], 2, 3]
>> 2521760495496 2521760589768
>> 2521760495112 2521760547336
深拷贝完全实现了我们想要的拷贝赋值。

2 扩展总结

类似于list有上述特点的还有集合set 、字典dict,即可变元素,因为只有可变元素在赋值后修改之后才可能出现上述问题,不可变元素要不整个元素修改,要不然不改变,不存在上述问题。
赋值语句的本质是为变量多起一个名字,即多一个内存指针,【最大的用处在于变量有了新名字原来的名字就可以删除了】。
类似于赋值语句出现的问题还可能出现在函数传参过程中,把原列表当作函数参数传入函数时,如果函数中列表发生修改,原列表也会跟着修改。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值