个人猜想(很遗憾失败了)
在硬盘或者系统中存在一个字符集
如果存在硬盘中,那么硬盘出厂的时候他的字符集所占用的空间就已经确定了。
如果存在于系统的话,硬盘应该在出厂的时候为系统设置一个存储系统字符集的地方。在安装系统的时候,把这个字符集放入约定的内存空间中。
当然,这个字符集不管是存在硬盘还是系统自带,硬盘中的这片内存区域是不允许改变的。所以不可变类型的原因就找到了。
文心一言告诉我,确实存在一个字符集,但并不存在于硬盘中,而是存在系统中,用于处理数据
不过可以确定的是,这些不可变数据的创建及存储是有一定规律的
测试一下
使用python输出不可变类型的内存地址
结论:
经过多次运行,这个内存地址在一个时间段内输出的内容是相同的
应该是某种机制在保护,程序结束后并不释放内存空间
而是等待一段时间的下次调用,用来节省资源的消耗
但是结果的差值都为32
a=1
b=2
print("a=",id(a))
print("b=",id(b))
"""
a= 140731726750504
b= 140731726750536
"""
"""
a= 140731562451752
b= 140731562451784
"""
使用 C语言输出不可变类型的内存地址
测试了一下C语言的,发他的内存地址是固定不会变化的
于是我想起来C语言编译型语言,于是又重新创建了一个代码相同的文件,结果竟然是相同的
#include <stdio.h>
int main() {
int a = 1;
int b = 2;
printf("变量a的内存地址是:%d\n", &a);
printf("变量b的内存地址是:%d\n", &b);
return 0;
}
//变量a的内存地址是:6422300
//变量b的内存地址是:6422296
尝试使用虚拟机的ubuntn系统下运行
python测试
结果显示差值为168,但是不会在一段时间内改变
a=1
b=2
print("a=",id(a))
print("b=",id(b))
"""
a= 10894368
b= 10894400
"""
C语言测试
发现每一次的结果都不同,但是每次都相差4,由此想到了系统架构是64还是32,一时间大量的疑问涌入脑中,好吧,时间有限,停止思考,疑问封存
什么是可变与不可变
可变不可变,是指内存中的那块内容(value)是否可以被改变
-
可变类型(mutable),创建后可以继续修改对象的内容(值)
字典、列表
-
不可变类型(unmutable) ,一旦创建就不可修改的对象(值)
数字, 字符串,元组
什么是深拷贝和浅拷贝
python中的copy 模块,可以实现拷贝功能
浅拷贝(就像快捷方式)
浅拷贝:引用(地址)拷贝,并没有产生新的空间。如果拷贝的是对象,原对象和copy对象都指向同一个内存空间,只拷贝父对象,不会拷贝对象的内部的子对象
- 不会产生新的空间
- 源对象和副本对象指向同一空间
- 如果拷贝的是对象,子对象不会拷贝(不产生新的空间)
用法: copy.copy(变量) 会进行拷贝
深拷贝(真正的复制)
- 会产生新的空间
- 能够保持各自的独立性
- 如果拷贝的是对象,子对象也会拷贝(产生新的空间)
深拷贝:会产生新的空间。如果拷贝的是对象,原对象和copy对象都指向不同的内存空间,会拷贝对象及其子对象(会产生新的空间)
用法:copy.deepcopy(变量名)
简单可变类型的拷贝
简单可变数据类型不管是深拷贝和浅拷贝,都会产生新的空间,而且保持各自的独立性
验证
浅拷贝
import copy
list1 = [2, 4, 6]
# 浅拷贝
list2 = copy.copy(list1)
print("list1=", list1, id(list1))
print("list2=", list2, id(list2))
list1.append(8)
print("list1=", list1, id(list1))
print("list2=", list2, id(list2))
# 测试结果
""""
list1= [2, 4, 6] 2366561172928
list2= [2, 4, 6] 2366558942976
list1= [2, 4, 6, 8] 2366561172928
list2= [2, 4, 6] 2366558942976
"""
深拷贝
import copy
list1=[2,4,6]
# 深拷贝
list2=copy.deepcopy(list1)
print("list1=", list1, id(list1))
print("list2=", list2, id(list2))
list1.append(8)
print("list1=", list1, id(list1))
print("list2=", list2, id(list2))
# 测试结果
"""
list1= [2, 4, 6] 2447599320576
list2= [2, 4, 6] 2447598755904
list1= [2, 4, 6, 8] 2447599320576
list2= [2, 4, 6] 2447598755904
"""
复杂可变类型的拷贝
复杂类型的内存地址是引用
list1 = [1, 3, 5]
list2 = [2, 4, 6]
list3 = [list1, list2]
print("list1=", list1, id(list1))
print("list2=", list2, id(list2))
print("list3=", list3, id(list3))
print("list3[0]=", list3[0], id(list3[0]))
"""
嵌套只是引用
list1= [1, 3, 5] 2090564943424
list2= [2, 4, 6] 2090564397632
list3= [[1, 3, 5], [2, 4, 6]] 2090562664192
list3[0]= [1, 3, 5] 2090564943424
"""
浅拷贝(对快捷方式创建快捷方式)
- 复杂可变类型的 浅拷贝,实际上是引用拷贝,无法保持独立性
验证
import copy
list1 = [1, 3, 5]
list2 = [2, 4, 6]
list3 = [list1, list2]
# 已知,复杂类型的内存地址是引用
# 所以对复杂类型进行浅拷贝
list4 = copy.copy(list3)
list1.append(7)
print("list1=", list1, id(list1))
print("list3=", list3, id(list3))
print("list4=", list4, id(list4))
print("list4=[0]", list4[0], id(list4[0]))
"""运行结果:在浅拷贝结束后
对简单类型进行数据的添加
复杂类型的内容会改变,浅拷贝的内容也会发生改变
而浅拷贝的地址改变了
所以浅拷贝针对复杂类型最顶层
list1= [1, 3, 5, 7] 3144178450048
list3= [[1, 3, 5, 7], [2, 4, 6]] 3144178363904
list4= [[1, 3, 5, 7], [2, 4, 6]] 3144178364544
list4=[0] [1, 3, 5, 7] 3144178450048
"""
深拷贝(真正的复制)
- 复杂可变类型的 深拷贝,此时会产生新的内存空间
验证
import copy
list1 = [1, 3, 5]
list2 = [2, 4, 6]
list3 = [list1, list2]
# 进行深拷贝
list4 = copy.deepcopy(list3)
list1.append(7)
print("list1=", list1, id(list1))
print("list3=", list3, id(list3))
print("list4=", list4, id(list4))
print("list4=[0]", list4[0], id(list4[0]))
"""运行结果:
深拷贝将复杂类型中的简单类型数据也进行了复制
实现了完全复制
list1= [1, 3, 5, 7] 1623394860736
list3= [[1, 3, 5, 7], [2, 4, 6]] 1623394774528
list4= [[1, 3, 5], [2, 4, 6]] 1623394775104
list4=[0] [1, 3, 5] 1623394775360
"""
简单不可变类型的拷贝(都是浅拷贝)
验证
import copy
def copy_popy():
tuple1=(1,3,5)
# 浅拷贝
tuple2=copy.copy(tuple1)
print("tuple1=",tuple1,id(tuple1))
print("tuple2=",tuple2,id(tuple2))
"""运行结果:
tuple1= (1, 3, 5) 2239384263296
tuple2= (1, 3, 5) 2239384263296
"""
tuple1=(1,3,5)
#深拷贝
tuple2=copy.deepcopy(tuple1)
print("tuple1=",tuple1,id(tuple1))
print("tuple2=",tuple2,id(tuple2))
"""运行结果
tuple1= (1, 3, 5) 2406599105152
tuple2= (1, 3, 5) 2406599105152
"""
复杂不可变类型的拷贝
复杂不可变类型的本质
import copy
list1=[1,3,5]
list2=[2,4,6]
tuple1=(list1,list2)
print("list1=",list1,id(list1))
print("tuple1=",tuple1,id(tuple1))
print("tuple1[0]=",tuple1[0],id(tuple1[0]))
"""运行结果
list1= [1, 3, 5] 2175399394816
tuple1= ([1, 3, 5], [2, 4, 6]) 2175399258432
tuple1[0]= [1, 3, 5] 2175399394816
"""
验证
浅拷贝
只关心最外层的数据类型是什么,如果是不可变类型,直接引用,没有办法保证数据的独立性
外层为不可变,内层为可变
import copy
list1=[1,3,5]
list2=[2,4,6]
tuple1=(list1,list2)
# 进行浅拷贝
tuple2=copy.copy(tuple1)
print("list1=",list1,id(list1))
print("tuple1=",tuple1,id(tuple1))
print("tuple1[0]=",tuple1[0],id(tuple1[0]))
print("tuple2=",tuple2,id(tuple2))
print("tuple2[0]=",tuple2[0],id(tuple2[0]))
"""运行结果
list1= [1, 3, 5] 2384705011392
tuple1= ([1, 3, 5], [2, 4, 6]) 2384704858432
tuple1[0]= [1, 3, 5] 2384705011392
tuple2= ([1, 3, 5], [2, 4, 6]) 2384704858432
tuple2[0]= [1, 3, 5] 2384705011392
"""
外层为可变,内层为不可变
import copy
list1=(1,3,5)
list2=(2,4,6)
tuple1=[list1,list2]
# 进行浅拷贝
tuple2=copy.copy(tuple1)
print("list1=",list1,id(list1))
print("tuple1=",tuple1,id(tuple1))
print("tuple1[0]=",tuple1[0],id(tuple1[0]))
print("tuple2=",tuple2,id(tuple2))
print("tuple2[0]=",tuple2[0],id(tuple2[0]))
"""运行结果
list1= (1, 3, 5) 2192295467648
tuple1= [(1, 3, 5), (2, 4, 6)] 2192295837376
tuple1[0]= (1, 3, 5) 2192295467648
tuple2= [(1, 3, 5), (2, 4, 6)] 2192295274688
tuple2[0]= (1, 3, 5) 2192295467648
"""
深拷贝
这个数据是否有可变的数据类型,如果有它就会为可变类型开辟多个空间存储数据和地址,达到保证数据独立性的作用
外层为可变类型
import copy
list1=(1,3,5)
list2=(2,4,6)
tuple1=[list1,list2]
# 进行深拷贝
tuple2=copy.deepcopy(tuple1)
print("list1=",list1,id(list1))
print("tuple1=",tuple1,id(tuple1))
print("tuple1[0]=",tuple1[0],id(tuple1[0]))
print("tuple2=",tuple2,id(tuple2))
print("tuple2[0]=",tuple2[0],id(tuple2[0]))
"""运行结果
list1= (1, 3, 5) 2050110790272
tuple1= [(1, 3, 5), (2, 4, 6)] 2050111160000
tuple1[0]= (1, 3, 5) 2050110790272
tuple2= [(1, 3, 5), (2, 4, 6)] 2050111074560
tuple2[0]= (1, 3, 5) 2050110790272
"""
外层为不可变类型
import copy
list1 = [1, 3, 5]
list2 = [2, 4, 6]
tuple1 = (list1, list2)
# 进行深拷贝
tuple2 = copy.deepcopy(tuple1)
print("list1=", list1, id(list1))
print("tuple1=", tuple1, id(tuple1))
print("tuple1[0]=", tuple1[0], id(tuple1[0]))
print("tuple2=", tuple2, id(tuple2))
print("tuple2[0]=", tuple2[0], id(tuple2[0]))
"""运行结果
list1= [1, 3, 5] 2221492256448
tuple1= ([1, 3, 5], [2, 4, 6]) 2221492103488
tuple1[0]= [1, 3, 5] 2221492256448
tuple2= ([1, 3, 5], [2, 4, 6]) 2221492102912
tuple2[0]= [1, 3, 5] 2221492170816
"""
内外都不可变
import copy
list1 = (1, 3, 5)
list2 = (2, 4, 6)
tuple1 = (list1, list2)
# 进行深拷贝
tuple2 = copy.deepcopy(tuple1)
print("list1=", list1, id(list1))
print("tuple1=", tuple1, id(tuple1))
print("tuple1[0]=", tuple1[0], id(tuple1[0]))
print("tuple2=", tuple2, id(tuple2))
print("tuple2[0]=", tuple2[0], id(tuple2[0]))
"""运行结果
list1= (1, 3, 5) 2647937981056
tuple1= ((1, 3, 5), (2, 4, 6)) 2647938197824
tuple1[0]= (1, 3, 5) 2647937981056
tuple2= ((1, 3, 5), (2, 4, 6)) 2647938197824
tuple2[0]= (1, 3, 5) 2647937981056
"""
注意:只要是可变类型不管是深拷贝都会开辟新的空间
切片拷贝(变量名[:])
切片拷贝,是一种浅拷贝,副本对象和原对象指向同一个空间
简单可变类型
list1 = [1, 3, 5]
list2 = list1[:]
print("list1=", list1, id(list1))
print("list2=", list2, id(list2))
list2.append(7)
print("list1=", list1, id(list1))
print("list2=", list2, id(list2))
"""运行结果
list1= [1, 3, 5] 1612210008768
list2= [1, 3, 5] 1612211181632
list1= [1, 3, 5] 1612210008768
list2= [1, 3, 5, 7] 1612211181632
"""
复杂不可变类型
list1 = [1, 3, 5]
list2 = [2, 4, 6]
tuple1=(list1,list2)
tuple2=tuple1[:]
print("list1=",list1,id(list1))
print("tuple1=",tuple1,id(tuple1))
print("tuple2=",tuple2,id(tuple2))
print("tuple1[0]=",tuple1[0],id(tuple1[0]))
print("tuple2[0]=",tuple2[0],id(tuple2[0]))
list1.append(7)
print("tuple2[0]=",tuple2[0],id(tuple2[0]))
"""运行结果得出,切片拷贝是浅拷贝
list1= [1, 3, 5] 2281363043008
tuple1= ([1, 3, 5], [2, 4, 6]) 2281364482816
tuple2= ([1, 3, 5], [2, 4, 6]) 2281364482816
tuple1[0]= [1, 3, 5] 2281363043008
tuple2[0]= [1, 3, 5] 2281363043008
tuple2[0]= [1, 3, 5, 7] 2281363043008
"""
字典拷贝 (字典名.copy())
字典提供一个copy()方法,也是浅拷贝,虽然地址发生改变,但是内部的对象仍然是链接状态
test_dict1={"age":[10,20,30]}
test_dict2=test_dict1.copy()
print("test_dict1=",test_dict1,id(test_dict1))
print("test_dict2=",test_dict2,id(test_dict2))
test_dict1["age"][0]=100
print("test_dict1=",test_dict1,id(test_dict1))
print("test_dict2=",test_dict2,id(test_dict2))
"""运行结果显示,字典拷贝为浅拷贝
test_dict1= {'age': [10, 20, 30]} 2561919905472
test_dict2= {'age': [10, 20, 30]} 2561921341312
test_dict1= {'age': [100, 20, 30]} 2561919905472
test_dict2= {'age': [100, 20, 30]} 2561921341312
"""