Python list与array关键区别及使用场景
一、关键区别
| 对比项 | list |
array.array |
|---|---|---|
| 元素类型 | 任意类型,可混合 | 必须同类型(如全是 int) |
| 内存存储 | 存对象指针(引用) | 存值本身 |
| 内存占用 | 大 | 小 |
| 导入 | 内置,直接用 | from array import array |
| 支持类型 | 所有 Python 对象 | 仅数字、字符等基本类型 |
| 丰富方法 | append、extend、sort、reverse、count、index、pop、remove、insert、clear、copy 等 |
方法少,主要是 append、extend、insert、pop、remove、fromlist、tolist 等 |
| 向量化运算 | ❌ | ❌ |
| 典型用途 | 通用容器 | 大量同类型数字,省内存 |
1. 元素类型
python
# list:什么都能放
lst = [1, "hello", 3.14, True, None, [1, 2], {"a": 1}]
print(lst) # [1, 'hello', 3.14, True, None, [1, 2], {'a': 1}]
python
from array import array
# array:只能放同类型
arr = array('i', [1, 2, 3, 4, 5]) # 'i' 表示 int
print(arr) # array('i', [1, 2, 3, 4, 5])
arr.append("hello") # ❌ TypeError: an integer is required
2. 内存布局
list :连续内存,但存的是指针,指向堆里的对象。
ini
lst: [ptr1][ptr2][ptr3]
↓ ↓ ↓
1 "hello" 3.14
(对象分散在堆内存,每个对象还有额外开销)
array :连续内存,直接存值本身。
ini
arr: [1][2][3][4][5]
每个格子直接存一个 int,没有额外指针和对象开销
3. 内存占用对比
python
import sys
from array import array
lst = list(range(1000))
arr = array('i', range(1000))
print(sys.getsizeof(lst)) # 约 8000+ 字节(存指针)
print(sys.getsizeof(arr)) # 约 4000 字节(存 int 值)
数据量越大,array 省内存的优势越明显。
4. 性能
python
import timeit
from array import array
# list
t1 = timeit.timeit('[x for x in range(100000)]', number=100)
# array
t2 = timeit.timeit('array("i", range(100000))', setup='from array import array', number=100)
print(t1, t2)
array 在存储同类型数字 时通常更快、更省内存,但功能少。
二、为什么 list 用法比 array 多很多?
根本原因:设计目标不同。
1. list 是"通用容器"
list 的设计目标是:什么都能装,什么都能干。
- 元素类型任意,所以需要处理各种对象的比较、排序、查找。
- 因此提供了大量通用方法:
sort、reverse、count、index、copy、clear、pop、remove、insert、extend等。 - 支持切片、推导式、嵌套、解包等高级用法。
python
lst = [3, 1, 4, 1, 5]
lst.sort() # 排序
lst.reverse() # 反转
lst.count(1) # 计数
lst.index(4) # 查找
lst[1:3] # 切片
[x**2 for x in lst] # 推导式
a, *rest = lst # 解包
2. array 是"专用存储"
array 的设计目标是:高效存储同类型基本数据。
- 元素类型固定,很多通用操作没必要或没法做。
- 它的重点是省内存、快速读写,不是"功能丰富"。
- 所以只提供最基本的增删查改,没有
sort(其实有tolist后可以排)、没有推导式、没有嵌套。
python
from array import array
arr = array('i', [3, 1, 4, 1, 5])
arr.append(6) # 增
arr.pop() # 删
arr[0] = 100 # 改
arr[1] # 查
arr.tolist() # 转成 list,之后才能用 list 的方法
3. list 是语言核心,array 是标准库模块
list是 Python 内置类型 ,有专门的语法支持([...]、推导式、切片)。array是标准库模块 ,需要import,没有语法糖,只是普通类。
4. list 的通用性带来更多需求
因为 list 什么都能装,所以用户会提出各种需求:
- 排序?加
sort。 - 反转?加
reverse。 - 计数?加
count。 - 查找?加
index。 - 复制?加
copy。
而 array 只装数字,用户对它的期待就是"省内存地存数字",不需要那么多花哨功能。
三、array 有哪些 list 没有的优势?
虽然 array 方法少,但它有 list 没有的:
1. 省内存
python
import sys
from array import array
lst = list(range(1000000))
arr = array('i', range(1000000))
print(sys.getsizeof(lst)) # 约 800 万字节
print(sys.getsizeof(arr)) # 约 400 万字节
2. 类型安全
python
from array import array
arr = array('i', [1, 2, 3])
arr.append("hello") # ❌ TypeError,防止存错类型
list 不会报错,可能埋下 bug。
3. 和 C 交互方便
array 可以直接和 C 的数组交互,list 不行。
4. 支持的类型码
python
from array import array
# 类型码:
# 'b' 有符号 char
# 'B' 无符号 char
# 'i' 有符号 int
# 'f' float
# 'd' double
arr = array('d', [1.0, 2.0, 3.0]) # double 数组
print(arr) # array('d', [1.0, 2.0, 3.0])
四、什么时候用 array?
| 场景 | 推荐 |
|---|---|
| 通用数据存储 | list |
| 元素类型混合 | list |
| 需要排序、切片、推导式 | list |
| 大量同类型数字,省内存 | array |
| 和 C 交互 | array |
| 科学计算 | numpy.ndarray |
| 需要向量化运算 | numpy.ndarray |
日常开发 99% 用 list ,array 只在内存敏感 + 同类型数字时才有优势。
五、list vs array vs numpy.ndarray
| 对比项 | list |
array.array |
numpy.ndarray |
|---|---|---|---|
| 元素类型 | 任意 | 同类型 | 同类型 |
| 内存 | 大(存指针) | 小(存值) | 小(存值) |
| 方法丰富度 | 最多 | 少 | 多(数值计算) |
| 向量化 | ❌ | ❌ | ✅ |
| 多维 | 嵌套列表 | ❌ | ✅ |
| 排序 | ✅ | 需转 list | ✅ |
| 切片 | ✅ | ✅ | ✅ |
| 导入 | 内置 | import array |
import numpy |
| 用途 | 通用 | 省内存 | 科学计算 |
六、一句话总结
| 问题 | 答案 |
|---|---|
| list 和 array 关键区别? | list 存任意类型指针 ,array 存同类型值 |
| 为什么 list 用法多? | list 是通用容器 ,内置类型,有语法支持;array 是专用存储,只装数字 |
| array 优势? | 省内存、类型安全、和 C 交互 |
| array 劣势? | 方法少、只能同类型、没有语法糖 |
| 日常用哪个? | 99% 用 list |
| 什么时候用 array? | 大量同类型数字 + 内存敏感 |
| 科学计算用什么? | numpy.ndarray |
核心记住:
list是"什么都能装的通用容器",所以方法多、用法多。array是"只能装同类型数字的省内存容器",所以方法少。- 用法多少的根源是设计目标不同:一个追求通用,一个追求高效存储。
- 日常开发用
list,内存敏感的同类型数字用array,科学计算用numpy。