python学习:可变与不可变数据类型,赋值,浅拷贝和深拷贝

本文探讨了Python中可变与不可变数据类型的特点及赋值机制,通过实例解析了浅拷贝与深拷贝的区别,并对比了切片操作与拷贝的不同之处。

可变与不可变数据类型以及赋值’=’

a = [x for x in range(5)]
b = a
c = 1
d = c
print('a', a, id(a))
print('b', b, id(b))
print('c', c, id(c))
print('d', d, id(d))

print('1*********************1')
a += [5]
c += 1
print('a', a, id(a))
print('b', b, id(b))
print('c', c, id(c))
print('d', d, id(d))

运行结果

a [0, 1, 2, 3, 4] 2271401961352
b [0, 1, 2, 3, 4] 2271401961352
c 1 1902341600
d 1 1902341600
1*********************1
a [0, 1, 2, 3, 4, 5] 2271401961352
b [0, 1, 2, 3, 4, 5] 2271401961352
c 2 1902341632
d 1 1902341600
不可变类型: 有一个标志符指向不可变数据类型的地址时,当其改变值,如a = 1,1 的地址是0x11111,a += 1 ,a 指向的地址会改变(2 的地址),因为1的地址不会改变
可变类型:有一个标志符指向可变数据类型是,当该标志符改变值,如a = [1,2,3],a的地址是0x11111, a.append(4),a指向的仍然是原来的[1,2,3]的地址0x111111,该地址被[1,2,3,4]占用。
可变类型:列表[],字典{}
不可变类型:非容器类型:str,num等,容器类型:元组()
赋值:是对象之间的引用传递,也就是多个对象指向同一个数据空间。

深拷贝,浅拷贝

print((lambda: '2*' * 50)())
a = [11, 22]
b = [33, 44]
c = [a, b]
print('a', a, id(a))
print('b', b, id(b))
print('c', c, id(c))
d = copy.copy(c)
e = copy.deepcopy(c)
print('d', d, id(d))
print('e', e, id(e))
print('c[0]', c[0], id(c[0]))
print('d[0]', d[0], id(d[0]))  # c[0]和d[0]地址相同,说明copy.copy浅拷贝是复制了c,引用了a和b的地址
print('e[0]', e[0], id(e[0]))  # e[0]和c[0]地址不同,深拷贝不仅复制了c,还复制了c中的 a 和 b 到其它的地址

结果

a [11, 22] 2271401961288
b [33, 44] 2271401960904
c [[11, 22], [33, 44]] 2271401961352
d [[11, 22], [33, 44]] 2271401959816
e [[11, 22], [33, 44]] 2271401960200
c[0] [11, 22] 2271401961288
d[0] [11, 22] 2271401961288
e[0] [11, 22] 2271401961544
对于可变数据类型:
浅拷贝:
c[0]和d[0]地址相同,说明copy.copy浅拷贝是复制了c到其它地址,‘引用’了a和b的地址
深拷贝:
e[0]和c[0]地址不同,深拷贝不仅复制了c到其它地址,还‘复制’了c中的 a 和 b 到其它的地址
拷贝对于不可变数据类型:
copy.copy和copy.deepcopy对于不可变类型没有意义,全部等价于对象之间的赋值操作:因为不可变类型中同一个数据如1,2等(假设1的地址是1110, 2的地址是1111),1的地址就只会是1110,2的地址就只会是1111,不会有其它的地址存储着1或者2。
所以说:copy和deepcopy和赋值是等价的

切片,深拷贝浅拷贝区别

a = [x for x in range(5)]
b = [x for x in 'abcde']
c = [a, b]
d = c[:]
e = copy.deepcopy(c)
print('c', c, id(c))
print('d', d, id(d))
print('e', e, id(e))
print('c[0]',c[0],id(c[0]))
print('d[0]',d[0],id(d[0]))
print('e[0]',e[0],id(e[0]))
a += [5]
print('操作之后。')
print('c[0]',c[0],id(c[0]))
print('d[0]',d[0],id(d[0]))  # 更深层的d[0],d[1]和c[0],c[1]地址相同,即切片只复制了c的最顶层数据到其它地址,没有复制a,b
print('e[0]',e[0],id(e[0]))

执行结果

c [[0, 1, 2, 3, 4], ['a', 'b', 'c', 'd', 'e']] 2584327141512
d [[0, 1, 2, 3, 4], ['a', 'b', 'c', 'd', 'e']] 2584327141448
e [[0, 1, 2, 3, 4], ['a', 'b', 'c', 'd', 'e']] 2584327120776
c[0] [0, 1, 2, 3, 4] 2584327120328
d[0] [0, 1, 2, 3, 4] 2584327120328
e[0] [0, 1, 2, 3, 4] 2584327141384
操作之后。
c[0] [0, 1, 2, 3, 4, 5] 2584327120328
d[0] [0, 1, 2, 3, 4, 5] 2584327120328
e[0] [0, 1, 2, 3, 4] 2584327141384
切片属于浅拷贝
更深层的d[0],d[1]和c[0],c[1]地址相同,即切片只复制了c的最顶层数据到其它地址,没有复制a,b
当a的地址的值改变,浅拷贝的d由于只引用了a,b的地址,d也会改变,深拷贝的e把c深层的a,b复制到了其它地址,所以e没有改变
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值