创建一个列表,底层到底在干啥
用python代码创建一个列表
a = [1,2,3,4]
>>> sys.getsizeof(a)
96
这样就结束了。
在创建一个[1,2,3,4]这样一个列表的时候,分配了一片96字节的内存。
列表的append操作
在前面我们创建了一个a列表
现在创建一个c列表并计算内存占用
>>> c=[1,2,3]
>>> sys.getsizeof(c)
88
在c列表使用append方法,并计算内存占用
>>> c.append(4)
>>> c
[1, 2, 3, 4]
>>> sys.getsizeof(c)
120
然而我们可以看到a列表和c列表,内容一样占用的内存不一样
>>> a
[1, 2, 3, 4]
>>> c
[1, 2, 3, 4]
>>> sys.getsizeof(a)
96
>>> sys.getsizeof(c)
120
c列表再次append一个元素,内存占用不变
>>> c
[1, 2, 3, 4]
>>> sys.getsizeof(c)
120
>>> c.append(5)
>>> c
[1, 2, 3, 4, 5]
>>> sys.getsizeof(c)
120
其实列表的append操作是这样的
假设列表k=[1,2]
执行k.append(3)
- 判断内存划分是否足够
- 足够,则直接放入元素“3”
- 不足够,则复制k列表中的内容到重新划分的一片更大内存,这个内存的区域会大于3个元素,再将元素“3”放入内存
并不是每次append元素都会增加内存,增加内存的规律是这样的
元素个数范围(N) | 0 | 1~4 | 5~8 | 9~16 | 17~25 | 26~35 | 36~46 | …… | 991~1120 |
---|---|---|---|---|---|---|---|---|---|
内存分配元素个数(M) | 0 | 4 | 8 | 16 | 25 | 35 | 46 | …… | 1120 |
M = ( N>>3 ) + (N < 9 ? 3 : 6)
创建元组
>>> b=(1,2,3,4)
>>> sys.getsizeof(b)
80
元组没有增删改查的操作,但是可以加乘法
>>> m=(1,2,3)
>>> n=(5,6,7)
>>> m+n
(1, 2, 3, 5, 6, 7)
>>> m*3
(1, 2, 3, 1, 2, 3, 1, 2, 3)
列表与元组的相似处
- 列表和元组都是扁平的数组
- 知道初始位置,查找一个元素可以O(1)
- 列表元组都适用于 加法 和 乘法
列表和元组的不同
- 创建列表用“[]”,创建元组用“()”
- 列表可以改变内容,改变长度
- 创建相同元素的列表和元组,元组占用的内存远远小于列表(其原因是列表需要存储间接指针)
>>> import sys
>>> a=[1,2,3,4]
>>> b=(1,2,3,4)
>>> sys.getsizeof(a)
96
>>> sys.getsizeof(b)
80
>>> c=[i for i in range(1000)]
>>> d=(i for i in range(1000))
>>> sys.getsizeof(c)
9024
>>> sys.getsizeof(d)
88