数组

1. 数组的定义

2. C++ 数组

3. Python 数组

本节探索基于数组的序列,主要基于 Python 语言的几种序列类 listtuplestr。这些类都是序列类型的,都支持下标取值 seq[i]

3.1 低层次数组

Python 不包含底层的连续数组,Python 的数组类型(不包含 array.array 或第三方库)都是引用类型的数组。Python 数组内的每一个值都是一个对象引用,复制它们会产生一个经典问题,即 Python 的 浅拷贝和深拷贝

关于 Python 引用对象的本质本章不会考虑,本章节先考虑 Python 内置的连续数组,然后实现一个底层上连续的数组类型,以模拟动态数组的特点。

3.2 使用紧凑数组

array.array 是标准库内的紧凑数组类型。有时候,使用 array 类型将比内置的整数类型获得更高的储存性能。

from array import array

primes = array('i', [2, 3, 5, 7, 11, 13, 17, 19])

我们在调用 primes[3] 时得到的是一个整型值(int 类型),这意味获取下标时,Python 将底层值自动转为 int 类型,不需要考虑类型转换问题。

其中 'i' 是标志码,表示实际储存的类型,可用的标志码如下:

代码数据类型Python 类型字节数
'b'signed charint1
'B'unsigned charint1
'u'wchar_tUnicode 字符2 或 4
'h'signed shortint2
'H'unsigned shortint2
'i'signed intint2 或 4
'I'unsigned intint2 或 4
'l'signed longint4
'L'unsigned longint4
'q'signed long longint8
'Q'unsigned long longint8
'f'floatfloat4
'd'doublefloat8

3.3 动态数组

Python 的列表类提供了对底层数组的抽象,该列表运行增添元素,对于列表内元素的总数没有明显的限制。为了提供这种抽象,Python 使用了 动态数组

一个列表通常关联一个底层数组,,该数组通常比列表的长度更长。如果用户创建了具有 55 个元素的列表,系统可能会预留能储存 88 个对象引用的底层数组。通过利用下面可用的储存单元,这样增添列表就会变得容易。

如果用户持续添加元素,那么最终储存空间会被耗尽。此时,应该向系统请求一个新的,更大的数组,然后用原来的值初始化该数组。这样,原来的储存空间就不需要了,被系统回收。这种策略直观看上去像寄居蟹一样。

Python 的 list 类确实基于这种策略,使用 sys.getsizeof() 可以得到对象的底层大小。我们可以做个实验证明:

import sys

data = []
for k in range(30):
    a = len(data)
    b = sys.getsizeof(data)
    print('[Length]: {:3d}, [Size]: {:4d}'.format(a, b))
    data.append(None)

结果:

[Length]:   0, [Size]:   56
[Length]:   1, [Size]:   88
[Length]:   2, [Size]:   88
[Length]:   3, [Size]:   88
[Length]:   4, [Size]:   88
[Length]:   5, [Size]:  120
[Length]:   6, [Size]:  120
[Length]:   7, [Size]:  120
[Length]:   8, [Size]:  120
[Length]:   9, [Size]:  184
[Length]:  10, [Size]:  184
[Length]:  11, [Size]:  184
[Length]:  12, [Size]:  184
[Length]:  13, [Size]:  184
[Length]:  14, [Size]:  184
[Length]:  15, [Size]:  184
[Length]:  16, [Size]:  184
[Length]:  17, [Size]:  248
[Length]:  18, [Size]:  248
[Length]:  19, [Size]:  248
[Length]:  20, [Size]:  248
[Length]:  21, [Size]:  248
[Length]:  22, [Size]:  248
[Length]:  23, [Size]:  248
[Length]:  24, [Size]:  248
[Length]:  25, [Size]:  312
[Length]:  26, [Size]:  312
[Length]:  27, [Size]:  312
[Length]:  28, [Size]:  312
[Length]:  29, [Size]:  312