Python可变对象和不可变对象
1、可变对象和不可变对象
在python中,一切皆对象,对象必有的三个属性:地址、类型、值
1.1 可变对象与不可变对象
当对象的值发生变化,但内存地址没有改变时,则说明是可变类型
当对象的值发生变化,内存地址也发生改变时,则说明是不可变类型
不可变对象(值传递):
内置类型的对象(int,float,bool,str,tuple,unicode)是不可变的。
可变对象(引用传递):
(list,set,dict)这样的内置类型的对象是可变的。
自定义类通常是可变的。
可变对象作为函数参数时候,是赋值地址给函数参数,函数内对其修改时候,会影响到变量的变化,例如:
l = [1,2,3] print(l) # [1, 2, 3] class A(): def change(self,lst:list): lst.append(9) a = A() a.change(l) print(l) #[1, 2, 3, 9]
2、深拷贝和浅拷贝
赋值: 只是复制了新对象的引用,不会开辟新的内存空间。
浅拷贝: 创建新对象,其内容是原对象的引用
深拷贝:和浅拷贝对应,深拷贝拷贝了对象的所有元素,包括多层嵌套的元素。深拷贝出来的对象是一个全新的对象,不再与原来的对象有任何关联。
2.1 对于不可变对象的深浅拷贝
import copy a=(1,2,3) print("=====赋值=====") b=a print(a) print(b) print(id(a)) print(id(b)) print("=====浅拷贝=====") b=copy.copy(a) print(a) print(b) print(id(a)) print(id(b)) print("=====深拷贝=====") b=copy.deepcopy(a) print(a) print(b) print(id(a)) print(id(b))
结果:
=====赋值===== (1, 2, 3) (1, 2, 3) 43481128 43481128 =====浅拷贝===== (1, 2, 3) (1, 2, 3) 43481128 43481128 =====深拷贝===== (1, 2, 3) (1, 2, 3) 43481128 43481128
不可变对象类型,没有被拷贝的说法,即便是用深拷贝,查看id的话也是一样的,如果对其重新赋值,也只是新创建一个对象,替换掉旧的而已。
一句话就是,不可变类型,不管是深拷贝还是浅拷贝,地址值和拷贝后的值都是一样的。
2.2 对于可变对象深浅拷贝
import copy a=[1,2,3] print("=====赋值=====") b=a print(a) print(b) print(id(a)) print(id(b)) print("=====浅拷贝=====") b=copy.copy(a) print(a) print(b) print(id(a)) print(id(b)) print("=====深拷贝=====") b=copy.deepcopy(a) print(a) print(b) print(id(a)) print(id(b))
结果:
=====赋值===== [1, 2, 3] [1, 2, 3] 37235144 37235144 =====浅拷贝===== [1, 2, 3] [1, 2, 3] 37235144 37191432 =====深拷贝===== [1, 2, 3] [1, 2, 3] 37235144 37210184
赋值: 值相等,地址相等
copy浅拷贝:值相等,地址不相等
deepcopy深拷贝:值相等,地址不相等
2.3 对于可变对象深浅拷贝(外层改变元素)
对于可变对象深浅拷贝(外层改变元素)
import copy l=[1,2,3,[4, 5]] l1=l #赋值 l2=copy.copy(l) #浅拷贝 l3=copy.deepcopy(l) #深拷贝 l.append(6) print(l) print(l1) print(l2) print(l3)
结果:
[1, 2, 3, [4, 5], 6] #l添加一个元素6 [1, 2, 3, [4, 5], 6] #l1跟着添加一个元素6 [1, 2, 3, [4, 5]] #l2保持不变 [1, 2, 3, [4, 5]] #l3保持不变
对于嵌套可变对象,赋值操作只是复制了一份地址,改变会随着原变量l改变。浅拷贝只是拷贝了第一层的内容,但是嵌套的内层还是属于地址复制,所以浅拷贝能保证第一层即外层保持不变。
2.4 对于可变对象深浅拷贝(内层改变元素)
import copy l=[1,2,3,[4, 5]] l1=l #赋值 l2=copy.copy(l) #浅拷贝 l3=copy.deepcopy(l) #深拷贝 l[3].append(6) print(l) print(l1) print(l2) print(l3)
结果:
[1, 2, 3, [4, 5, 6]] #l[3]添加一个元素6 [1, 2, 3, [4, 5, 6]] #l1跟着添加一个元素6 [1, 2, 3, [4, 5, 6]] #l2跟着添加一个元素6 [1, 2, 3, [4, 5]] #l3保持不变
1.外层添加元素时,浅拷贝不会随原列表变化而变化;内层添加元素时,浅拷贝才会变化。
2.无论原列表如何变化,深拷贝都保持不变。
3.赋值对象随着原列表一起变化。
分类:
Python / 基础知识
标签:
Python
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本