数据类型
为什么要有数据类型?
计算机只会执行预先写好的指令而已,这些指令也只是操作数据或者设备。所谓程序,基本上就是告诉计算机要操作的数据和执行的指令序列, 即对什么数据做什么操作。
比如说:
- 读文档,就是将数据从磁盘加载到内存,然后输出到显示器上
- 写文档,就是将数据从内存写回磁盘。
- 播放音乐,就是将音乐的数据加载到内存,然后写到声卡上。
- 聊天,就是从键盘接收聊天数据,放到内存,然后传给网卡,通过网络传给另一个人的网卡,再从网卡传到内存,显示在显示器上。
基本上,所有数据都需要放到内存进行处理,程序的很大一部分工作就是操作在内存中的数据。
数据
数据是什么?
数据在计算机内部都是二进制,不方便操作,为了方便操作数据,高级语言引入了"数据类型"和"变量"的概念。
数据类型
数据类型用于对数据归类,方便理解和操作,如list int str dict set tuple 等
int 数字主要用于计算
bool 就两种True,False 就是反应条件的正确与否
str 字符串
tuple 元组称为只读列表,数据可以被查询,但不能被修改
list 列表,可以存储不同的数据类型
dict 字典,以键值对的形式存储数据
set 集合,无序的,不重复的数据集合
变量
为了操作数据,需要把数据存放到内存中,所谓内存在程序看来就是一块有地址编号的连续的空间,放到内存中的某个位置后,为了方便地找到和操作这个数据,需要给这个位置起一个名字。编程语言通过变量这个概念来表示这个过程。
可变类型与不可变类型
不可变类型
如果是不可变类型,在对对象本身操作的时候,必须在内存中新申请一块区域
对不可变类型的变量重新赋值,实际上是重新创建一个不可变类型的对象,并将原来的变量重新指向新创建的对象(如果没有其他变量引用原有对象的话(即引用计数为0),原有对象就会被回收)。
数据类型:数字 字符串 元组
可变类型
如果是可变类型,对对象操作的时候,不需要再在其他地方申请内存,只需要在此对象后面连续申请(+/-)即可,也就是它的address会保持不变,但区域会变长或者变短。
数据类型:列表 字典
赋值与深浅copy
赋值,只是创建一个变量,该变量指向原来内存地址
浅copy
举个栗子:
import copy n1 = {"k1": "wu", "k2": 123, "k3": ["alex", 678]} n3 = copy.copy(n1) # 浅拷贝 print("第一层字典的内存地址:") print(id(n1)) print(id(n3)) print("第二层嵌套的列表的内存地址:") print(id(n1["k3"])) print(id(n3["k3"]))
输出结果:
第一层字典的内存地址: 6516024 6516096 第二层嵌套的列表的内存地址: 36995720 36995720
通过以上结果可以看出,进行浅拷贝时,我们的字典第一层n1和n3指向的内存地址已经改变了,但是对于第二层里的列表并没有拷贝,它的内存地址还是一样的。原理如下图:
结论:所以对于浅拷贝,字典、列表、元组等类型,它们只拷贝第一层地址。
深copy
举个栗子:
import copy n1 = {"k1": "wu", "k2": 123, "k3": ["alex", 678]} n4 = copy.deepcopy(n1) # 深拷贝 print("第一层字典的内存地址:") print(id(n1)) print(id(n4)) print("第二层嵌套的列表的内存地址:") print(id(n1["k3"])) print(id(n4["k3"]))
输出结果:
第一层字典的内存地址: 31157560 35463600 第二层嵌套的列表的内存地址: 35947144 35947336
通过以上结果发现,进行深拷贝时,字典里面的第一层和里面嵌套的地址都已经变了。对于深拷贝,它会拷贝多层,将第二层的列表也拷贝一份,如果还有第三层嵌套,那么第三层的也会拷贝,但是对于里面的最小元素,比如数字和字符串,这里就是“wu”,123,“alex”,678之类的,按照python的机制,它们会共同指向同一个位置,它的内存地址是不会变的。原理如下图:
结论:对于深拷贝,字典、列表、元组等类型,它里面嵌套多少层,就会拷贝多少层出来,但是最底层的数字和字符串地址不变。
参考:https://www.jianshu.com/p/e62c0835c652
https://www.cnblogs.com/jin-xin/articles/7562422.html
http://www.cnblogs.com/Jacck/p/7790049.html
https://www.cnblogs.com/doublexi/p/8745792.html