python深\浅拷贝问题

文章详细阐述了Python中元组的不可变性,指的是元组内元素的内存地址不可变,而非内容。同时解释了`is`与`==`的区别,以及Python对小整数的缓存机制。接着讨论了直接赋值、浅拷贝和深拷贝的区别,强调在数据独立性方面的差异,并通过示例说明了它们在处理可变对象时的不同行为。最后指出深拷贝在多数情况下的必要性,并提醒开发者注意浅拷贝可能导致的陷阱。
摘要由CSDN通过智能技术生成

1.首先是元组不可变,指的并不是元组内容不可变,是指元组中各项元素的内存地址不可变。

例如    a=(1,2,3,[4,5])  ;   a[-1].append(6);

结果: a=(1,2,3,[4,5,6])

实际上 id(a[-1])并没有改变

这也就是所说的“元组不可变”。

2.is  与 ==

is比较的是两个变量的地址是否相同,具有更快的比较效率(但不同地址的元素也可能值相同)

==就是比较2个变量的值是否相等

同时,python中有个特性:-25~256的整数,是预先缓存好的(但是好像3.11中,所有的整数都是这样)

即a=1,b=1  实际上他俩的id是相同的,直接指向1原先缓存的地址。

先说结论:在数据的独立性方面---直接赋值<浅拷贝<深拷贝

3.直接赋值

其实就是对象的引用(别名)

a=xxxx

b=a

b就是a的别名, a,b的地址是完全相同的,因此a怎么变,b也跟着变;b怎么变,a也跟着变。

就是说,a,b是一回事

4.浅拷贝

拷贝父对象,不会拷贝对象的内部的子对象。

例如:

a=[1,2,3,4,[5,6]]
b=a.copy()
a.append(123)
print(a)  
print(b)

输出:

                                [1, 2, 3, 4, [5, 6], 123]
                                [1, 2, 3, 4, [5, 6]]

此时a,b已经是不同的地址了,b拷贝了a的内容(父对象),但a中的可变内容([5,6]), a,b是共同指向的。  这就是所说的:只拷贝了父对象,没有拷贝内部的子对象

所以,a,b从整体上是不同的,但内部的可变对象---[5,6]仍是共享的(从效果上看是共享效果,实际上地址也不同)

例如:

a=[1,2,3,4,[5,6]]
b=a.copy()
a[-1].append(123)
print(a)
print(b)

输出:

                                        [1, 2, 3, 4, [5, 6, 123]]
                                        [1, 2, 3, 4, [5, 6, 123]]

这就是浅拷贝,从整体上变的时候,a,b是独立的;一旦改的是内部的可变内容,两者就一起受影响。

a=[1,2,3,4,[5,6]]
b=a.copy()
a.append(111)
b[-1].append(123)
print(a)
print(b)

输出:

                                                [1, 2, 3, 4, [5, 6, 123], 111]
                                                [1, 2, 3, 4, [5, 6, 123]]

第一个append,只改变了a,在a的末尾加了个111.

第二个append,同时改变了a,b。

5.深拷贝

 copy 模块的 deepcopy 方法,完全拷贝了父对象及其子对象

完全独立了此时,注意下语法

import copy
a=[1,2,3,4,[5,6]]
b=copy.deepcopy(a)
a.append(111)
b[-1].append(123)
print(a)
print(b)

输出:

                                        [1, 2, 3, 4, [5, 6], 111]
                                        [1, 2, 3, 4, [5, 6, 123]]

各自改各自的,互不影响。

其实,大部分时间都是深拷贝的需求,但会陷入浅拷贝的坑,一定要注意。

此bug曾坑过我一次。。。而且在缺失这部分的知识时,此bug极难发现。

在此做个记录。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值