-
计算机的作用
-
-
问题:计算机如何计算1+2
-
转换成二进制的数值
-
在计算机中开辟两块内存空间
-
将1和2存储到这两块内存空间中
-
-
变量的概念
-
变量就是引用.变量其实表示的就是计算机中的一块内存
-
严谨:变量其实就是内存地址
-
-
一块内存空间会有两个默认属性
-
内存空间大小
-
bit
-
byte
-
kb...
-
-
内存地址
-
作用:寻址
-
-
-
int类型的变量默认开启4个字节空间大小的内存地址
-
-
理解a=10的内存图(引用,指向)
-
指向:如果变量或者引用存储了某块内存空间地址,则该变量或者引用指向该块内存
-
-
不同数据占用内存空间的大小不同
顺序表
-
数组中的数据类型为什么要一致?
-
数组在内存中是以链表的方式进行存储,会在内存中连续开辟一个空间给元素进行存储.比如数组中存储了a = array([1,2,3]),那么会在内存中连续开辟3个空间,变量a指向第一个空间地址也就是元素1的存储地址,暂且空间地址记为0x0.整型在内存中默认开辟4个字节大小,那么1向后偏移4个字节为2,内存地址记为0x4,同理元素3为0x8.所以只需记录了第一个元素1的内存地址,那么只要向后偏移以4位单位的字节就能找到连续开辟内存空间的其他元素.
-
-
为什么数组索引从0开始?
-
为了更方便的让计算机进行变量寻址和偏移.
-
a[0] -> 0-> 0x0
-
a[1] -> 1-> 0x4
-
a[2] -> 2-> 0x8
-
-
在顺序表中的插入和删除操作浪费性能
-
列表或数组中有300W个元素,如果我在第二个位置插入或者删除1个元素,那么后面的299W个元素的内存地址都将向前或向后一位,很浪费性能.
-
-
数组与列表的区别
-
数组:数组在内存中为元素开辟的空间是连续的
-
列表:列表在内存中为元素开辟的空间是非连续的,但它有另外一个连续的空间顺序的存放元素对应的地址
-
-
单数据类型顺序表的内存图(内存连续开辟)
-
多数据类型顺序表的内存图(内存非连续开辟)
-
顺序表的弊端:顺序表的结构需要预先直到数据大小来申请连续的存储空间,而在扩充时又需要进行数据的搬迁.
python内存管理机制
-
1.计数器
-
a=10,b=a(a的引用计数为2) del b(引用计数-1) del a(引用计数为0)
-
-
2.垃圾回收
-
引用计数为主,标记清除和分代回收为辅
-
标记清除:
-
a = [1,2] b = [3,4] a.append(b) b.append(a) 当a和b形成环状引用且引用计数都为2,当我del a del b时,它们的引用计数都为1,但此时已经删除了变量a和b,但它们的值还是存在内存中并且不能被使用,变成了垃圾.标记清除就是为了解决这种情况,把它们两个的引用计数都-1.
-
-
分代回收:
-
存在3个列表分为0代,1代和2代.轮询这3个列表,查看变量的引用计数是否为1和环状引用
-
0代:当长度大于700时进行轮询
-
1代:每扫描10次0代进行扫描1次1代
-
2代:每扫描10次1代进行扫描1次2代
-
-
-
-
3.内存池:
-
小数据池
-
-
1.开启一个新的对象会存放在双端链表中
-
2.通过引用计数来确定是不是垃圾,但是会有循环引用的问题
-
3.为了解决循环引用,使用了标记清除,标记清除就是将循环引用的内容引用计数都-1
-
4.为了解决多次扫描一个双端链表,使用了分代回收.一共是3代,0、1、2代
-
5.当0代的长度>700时扫描一次0代,每扫描10次0代就会扫描1次1代
-
6.每扫描10次1代就扫描1次2代