Python內置模塊:array
1. 模塊概述
1.1 什么是array模塊
array模塊是Python標準庫中的一個內置模塊,它提供了一種高效存儲基本數據類型(如整數、浮點數)的序列結構。與列表(list)相比,array在存儲單一數據類型時更加緊湊,內存占用更小,性能更高。
原理:array模塊底層使用C語言的數組實現,所有元素必須是相同類型,這使得它在內存中是連續存儲的,訪問速度更快
1.2 為什么使用array
- 內存效率:存儲相同數量的數據時,array比list占用更少內存
- 性能優勢:數值計算操作比list更快
- 類型安全:確保數組中所有元素類型一致
- 二進制數據交互:方便與C/C++代碼或二進制文件交互
1.3 適用場景舉例
- 需要處理大量數值數據
- 內存受限的環境
- 需要與C/C++代碼交互
- 處理二進制數據文件
2. 類型碼
2.1 類型碼表
array模塊使用單字符類型碼來指定數組中元素的類型。以下是完整的類型碼表
| 類型碼 | Python 類型 | 最小字節數 | 備注 |
| 'b' | int | 1 | 有符號字節 |
| 'B' | int | 1 | 無符號字節 |
| 'u' | Unicode字符 | 2/4 | Python 3.3+不推薦 |
| 'w' | Unicode字符 | 4 | 推薦替代'u' |
| 'h' | int | 2 | 有符號短整數 |
| 'H' | int | 2 | 無符號短整數 |
| 'i' | int | 2 | 有符號整數 |
| 'I' | int | 2 | 無符號整數 |
| 'l' | int | 4 | 有符號長整數 |
| 'L' | int | 4 | 無符號長整數 |
| 'q' | int | 8 | 有符號長長整數 |
| 'Q' | int | 8 | 無符號長長整數 |
| 'f' | float | 4 | 單精度浮點數 |
| 'd' | float | 8 | 雙精度浮點數 |
2.2 類型碼選擇建議
1. 根據數據范圍選擇整數類型:
- 小范圍整數(0-255):
'B'或'b' - 中等范圍整數:
'h'或'H' - 大整數:
'l'、'L'、'q'或'Q'
2. 浮點數選擇:
- 一般精度:
'f' - 高精度:
'd'
3. Unicode字符:
- 推薦使用
'w'而非'u',因為'u'將在Python 3.16中移除
3. 創建和初始化array
3.1 array構造函數
class array.array(typecode[, initializer])
參數:
typecode:指定數組元素類型的單字符代碼initializer:可選,初始化數組的數據,可以是:- bytes或bytearray對象
- Unicode字符串(僅適用于
'u'或'w'類型碼) - 可迭代對象(列表、元組等)
返回值:返回一個新的array對象
3.2 創建array的多種方式
3.2.1 創建空數組
import array
# 創建空整數數組
int_arr = array.array('i')
print(int_arr)
# 創建空浮點數數組
float_arr = array.array('f')
print(float_arr)
3.2.2 從列表初始化
import array
# 從列表創建整數數組
numbers = array.array('i', [1,2,3,4,5])
print(numbers)
# 從列表創建浮點數數組
temps = array.array('f', [23.5,27.8,19.2])
print(temps)
3.2.3 從bytes/bytearray初始化
import array
# 從bytes創建數組
data = b'\x01\x00\x00\x00\x02\x00\x00\x00' # 兩個32位整數
int_arr = array.array('i', data)
print(int_arr)
# 從bytearray創建
byte_data = bytearray(b'\x01\x02\x03\x04')
byte_arr = array.array('B', byte_data)
print(byte_arr)
3.2.4 從Unicode字符串初始化
import array
# 創建Unicode字符數組
text = array.array('w', '你好Python')
print(text)
3.3 注意事項
- 類型一致性:所有元素必須是相同類型
- 類型轉換:初始化時會自動嘗試將元素轉換為指定類型
- 錯誤處理:類型不匹配會引發TypeError
- 內存分配:數組大小固定后,內存連續分配
4. array基本操作
4.1 訪問元素
array支持所有序列操作,包括索引、切片等。
import array
numbers = array.array('i', [10, 20, 30, 40, 50])
# 索引訪問
print(numbers[0]) # 10
print(numbers[-1]) # 50
# 切片操作
print(numbers[1:3]) # array('i', [20, 30])
print(numbers[:3]) # array('i', [10, 20, 30])
print(numbers[3:]) # array('i', [40, 50])
# 修改元素
numbers[0] = 100
print(numbers) # array('i', [100, 20, 30, 40, 50])
4.2 添加元素
4.2.1 append()方法
功能:在數組末尾添加一個元素
import array
arr = array.array('d')
arr.append(3.14)
arr.append(2.71)
print(arr) # array('f', [3.14, 2.71])
4.2.2 extend()方法
功能:從可迭代對象添加多個元素
import array
arr = array.array('i', [1, 2, 3])
arr.extend([4, 5, 6])
print(arr) # array('i', [1, 2, 3, 4, 5, 6])
# 也可以擴展另一個array,但類型必須匹配
other = array.array('i', [7, 8])
arr.extend(other)
print(arr) # array('i', [1, 2, 3, 4, 5, 6, 7, 8])
4.2.3 insert()方法
功能:在指定位置插入元素
import array
arr = array.array('B', [1, 2, 4, 5])
arr.insert(2, 3) # 在索引2處插入3
print(arr) # array('B', [1, 2, 3, 4, 5])
4.3 刪除元素
4.3.1 pop()方法
功能:移除并返回指定位置的元素
import array
arr = array.array('i', [10, 20, 30, 40])
print(arr.pop()) # 40 (默認移除最后一個)
print(arr.pop(0)) # 10 (移除第一個)
print(arr) # array('i', [20, 30])
4.3.2 remove()方法
功能:移除第一個匹配的元素
import array
arr = array.array('i', [1, 2, 3, 2, 4])
arr.remove(2) # 移除第一個2
print(arr) # array('i', [1, 3, 2, 4])
4.3.3 clear()方法
功能:清空數組(Python 3.13+)
import array
arr = array.array('d', [1.1, 2.2, 3.3])
arr.clear()
print(arr) # array('d')
import array
arr = array.array('d', [1.1, 2.2, 3.3])
arr = array.array('d') # 創建一個新的空數組
print(arr) # array('d')
arr = array.array('d', [1.1, 2.2, 3.3])
del arr[:] # 刪除數組中的所有元素
print(arr) # array('d')
arr = array.array('d', [1.1, 2.2, 3.3])
while len(arr) > 0:
arr.pop() # 逐個刪除元素
print(arr) # array('d')
arr = array.array('d', [1.1, 2.2, 3.3])
arr[:] = [] # 使用切片賦值清空數組
print(arr) # array('d')
4.4 其他常用操作
4.4.1 count()方法
功能:統計元素出現次數
import array
arr = array.array('i', [1, 2, 2, 3, 2, 4])
print(arr.count(2)) # 3
4.4.2 index()方法
功能:查找元素首次出現的位置
import array
arr = array.array('i', [10, 20, 30, 20, 40])
print(arr.index(20)) # 輸出 1,因為 20 第一次出現在索引 1
print(arr.index(20, 2)) # 輸出 3,從索引 2 開始查找 20,第一次出現在索引 3
4.4.3 reverse()方法
功能:反轉數組
import array
arr = array.array('h', [1, 2, 3, 4])
arr.reverse()
print(arr) # array('h', [4, 3, 2, 1])
5. 數組與二進制數據交互
5.1 tobytes()和frombytes()
5.1.1 tobytes()
功能:將數組轉換為字節表示
import array
arr = array.array('i', [1, 2, 3])
byte_data = arr.tobytes()
print(byte_data) # b'\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00'
5.1.2 frombytes()
功能:從字節數據重建數組
import array
arr = array.array('i', [1, 2, 3])
byte_data = arr.tobytes()
new_arr = array.array('i')
new_arr.frombytes(byte_data)
print(new_arr) # array('i', [1, 2, 3])
5.2 tofile()和fromfile()
5.2.1 tofile()
功能:將數組寫入文件
import array
arr = array.array('d', [1.1, 2.2, 3.3])
with open('data.bin', 'wb') as f:
arr.tofile(f)
5.2.2 fromfile()
功能:從文件讀取數組數據
import array
new_arr = array.array('d')
with open('data.bin', 'rb') as f:
new_arr.fromfile(f, 3) # 讀取3個元素
print(new_arr) # array('d', [1.1, 2.2, 3.3])
5.3 byteswap()
功能:交換字節順序(大小端轉換)
import array
arr = array.array('h', [1, 256]) # 0x0001, 0x0100
print(arr.tobytes()) # b'\x01\x00\x00\x01'
arr.byteswap()
print(arr.tobytes()) # b'\x00\x01\x01\x00'
print(arr) # array('h', [256, 1])
6. 特性和性能考慮
6.1 緩沖區接口
array實現了緩沖區協議,可以高效地與其它支持緩沖區接口的對象交互
import array
arr = array.array('i', [1, 2, 3, 4, 5])
# 使用 memoryview 訪問緩沖區
mv = memoryview(arr)
print(mv[1:3].tolist()) # [2, 3]
# 修改數據會反映到原數組
mv[2] = 99
print(arr) # array('i', [1, 2, 99, 4, 5])
6.2 性能比較
表2: array與list性能比較(操作100萬個元素)
| 操作 | array('i') | list | 優勢比 |
| 創建時間 | 0.05s | 0.12s | 2.4x |
| 內存占用 | 4MB | 8MB | 2x |
| 遍歷速度 | 0.03s | 0.05s | 1.7x |
| 求和速度 | 0.02s | 0.08s | 4x |
6.3 類型轉換
import array
# array轉list
arr = array.array('f', [1.1, 2.2, 3.3])
lst = arr.tolist()
print(lst) # [1.1, 2.2, 3.3]
# list轉array
new_arr = array.array('f', lst)
print(new_arr) # array('f', [1.1, 2.2, 3.3])
7. 應用舉例
7.1 處理大型數值數據集示例
import array
import random
import time
# 生成100萬個隨機數
start = time.time()
data = array.array('d', (random.random() for _ in range(1_000_000)))
print(f"生成array耗時:{time.time() - start:.3f}秒")
# 計算平均值
start = time.time()
mean = sum(data) / len(data)
print(f"計算平均值耗時:{time.time() - start:.4f}秒")
print(f"平均值:{mean:.4f}")
# 內存占用比較
import sys
list_data = list(data)
print(f"array內存占用:{sys.getsizeof(data) / 1_000_000:.2f}MB")
print(f"list內存占用:{sys.getsizeof(list_data) / 1_000_000:.2f}MB")
7.2 二進制文件處理示例
import array
def save_sensor_data(filename, data):
"""保存傳感器數據到二進制文件"""
arr = array.array('H', data)
with open(filename, 'wb') as f:
arr.tofile(f)
def load_sensor_data(filename, count):
"""從二進制文件加載傳感器數據"""
arr = array.array('H')
with open(filename, 'rb') as f:
arr.fromfile(f, count)
return arr
# 模擬傳感器數據
sensor_data = [100, 105, 110, 115, 120, 118, 116, 114]
# 保存并加載數據
save_sensor_data('sensor.bin', sensor_data)
loaded_data = load_sensor_data('sensor.bin', len(sensor_data))
print("加載的數據:", loaded_data.tolist())
7.3 與NumPy交互示例
雖然array模塊功能有限,但可以輕松轉換為NumPy數組進行高級數值計算:
import array
import numpy as np
# 創建array
arr = array.array('d', [1.1, 2.2, 3.3, 4.4])
# 轉換為NumPy數組
np_arr = np.array(arr)
print("NumPy數組:", np_arr)
# 執行NumPy操作
print("平方:", np.square(np_arr))
print("平均值:", np.mean(np_arr))
# 轉換回array
new_arr = array.array('d', np_arr.tolist())
print("轉換回array:", new_arr)
| 類型碼 | C 類型 | Python 類型 | 最小字節數 | 備注 |
|---|---|---|---|---|
'b' |
signed char | int | 1 | 有符號字節 |
'B' |
unsigned char | int | 1 | 無符號字節 |
'u' |
wchar_t | Unicode字符 | 2/4 | 平臺相關,Python 3.3+不推薦 |
'w' |
Py_UCS4 | Unicode字符 | 4 | 推薦替代'u' |
'h' |
signed short | int | 2 | 有符號短整數 |
'H' |
unsigned short | int | 2 | 無符號短整數 |
'i' |
signed int | int | 2 | 有符號整數 |
'I' |
unsigned int | int | 2 | 無符號整數 |
'l' |
signed long | int | 4 | 有符號長整數 |
'L' |
unsigned long | int | 4 | 無符號長整數 |
'q' |
long long | int | 8 | 有符號長長整數 |
'Q' |
unsigned long long | int | 8 | 無符號長長整數 |
'f' |
float | float | 4 | 單精度浮點數 |
'd' |
double | float | 8 | 雙精度浮點數 |
2.2 類型碼選擇建議
-
根據數據范圍選擇整數類型:
- 小范圍整數(0-255):
'B'或'b' - 中等范圍整數:
'h'或'H' - 大整數:
'l'、'L'、'q'或'Q' -
浮點數選擇:
- 一般精度:
'f' - 高精度:
'd' -
Unicode字符:
- 推薦使用
'w'而非'u',因為'u'將在Python 3.16中移除
3. 創建和初始化array
3.1 array構造函數
原型:
class array.array(typecode[, initializer])
參數:
typecode:指定數組元素類型的單字符代碼initializer:可選,初始化數組的數據,可以是:- bytes或bytearray對象
- Unicode字符串(僅適用于
'u'或'w'類型碼) - 可迭代對象(列表、元組等)
返回值:返回一個新的array對象
3.2 創建array的多種方式
3.2.1 創建空數組
import array
# 創建空整數數組
int_arr = array.array('i')
print(int_arr) # array('i')
# 創建空浮點數數組
float_arr = array.array('f')
print(float_arr) # array('f')
3.2.2 從列表初始化
# 從列表創建整數數組
numbers = array.array('i', [1, 2, 3, 4, 5])
print(numbers) # array('i', [1, 2, 3, 4, 5])
# 從列表創建浮點數數組
temps = array.array('f', [23.5, 27.8, 19.2])
print(temps) # array('f', [23.5, 27.8, 19.2])
3.2.3 從bytes/bytearray初始化
# 從bytes創建數組
data = b'\x01\x00\x00\x00\x02\x00\x00\x00' # 兩個32位整數
int_arr = array.array('i', data)
print(int_arr) # array('i', [1, 2])
# 從bytearray創建
byte_data = bytearray(b'\x01\x02\x03\x04')
byte_arr = array.array('B', byte_data)
print(byte_arr) # array('B', [1, 2, 3, 4])
3.2.4 從Unicode字符串初始化
# 創建Unicode字符數組
text = array.array('w', '你好Python')
print(text) # array('w', '你好Python')
3.3 注意事項
- 類型一致性:所有元素必須是相同類型
- 類型轉換:初始化時會自動嘗試將元素轉換為指定類型
- 錯誤處理:類型不匹配會引發TypeError
- 內存分配:數組大小固定后,內存連續分配
4. array基本操作
4.1 訪問元素
array支持所有序列操作,包括索引、切片等。
numbers = array.array('i', [10, 20, 30, 40, 50])
# 索引訪問
print(numbers[0]) # 10
print(numbers[-1]) # 50
# 切片操作
print(numbers[1:3]) # array('i', [20, 30])
print(numbers[:3]) # array('i', [10, 20, 30])
print(numbers[3:]) # array('i', [40, 50])
# 修改元素
numbers[0] = 100
print(numbers) # array('i', [100, 20, 30, 40, 50])
4.2 添加元素
4.2.1 append()方法
功能:在數組末尾添加一個元素
arr = array.array('f')
arr.append(3.14)
arr.append(2.71)
print(arr) # array('f', [3.14, 2.71])
4.2.2 extend()方法
功能:從可迭代對象添加多個元素
arr = array.array('i', [1, 2, 3])
arr.extend([4, 5, 6])
print(arr) # array('i', [1, 2, 3, 4, 5, 6])
# 也可以擴展另一個array,但類型必須匹配
other = array.array('i', [7, 8])
arr.extend(other)
print(arr) # array('i', [1, 2, 3, 4, 5, 6, 7, 8])
4.2.3 insert()方法
功能:在指定位置插入元素
arr = array.array('B', [1, 2, 4, 5])
arr.insert(2, 3) # 在索引2處插入3
print(arr) # array('B', [1, 2, 3, 4, 5])
4.3 刪除元素
4.3.1 pop()方法
功能:移除并返回指定位置的元素
arr = array.array('i', [10, 20, 30, 40])
print(arr.pop()) # 40 (默認移除最后一個)
print(arr.pop(0)) # 10 (移除第一個)
print(arr) # array('i', [20, 30])
4.3.2 remove()方法
功能:移除第一個匹配的元素
arr = array.array('i', [1, 2, 3, 2, 4])
arr.remove(2) # 移除第一個2
print(arr) # array('i', [1, 3, 2, 4])
4.3.3 clear()方法
功能:清空數組(Python 3.13+)
arr = array.array('d', [1.1, 2.2, 3.3])
arr.clear()
print(arr) # array('d')
4.4 其他常用操作
4.4.1 count()方法
功能:統計元素出現次數
arr = array.array('i', [1, 2, 2, 3, 2, 4])
print(arr.count(2)) # 3
4.4.2 index()方法
功能:查找元素首次出現的位置
arr = array.array('i', [10, 20, 30, 20, 40])
print(arr.index(20)) # 1
print(arr.index(20, 2)) # 3 (從索引2開始查找)
4.4.3 reverse()方法
功能:反轉數組
arr = array.array('h', [1, 2, 3, 4])
arr.reverse()
print(arr) # array('h', [4, 3, 2, 1])
5. 數組與二進制數據交互
5.1 tobytes()和frombytes()
5.1.1 tobytes()
功能:將數組轉換為字節表示
arr = array.array('i', [1, 2, 3])
byte_data = arr.tobytes()
print(byte_data) # b'\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00'
5.1.2 frombytes()
功能:從字節數據重建數組
new_arr = array.array('i')
new_arr.frombytes(byte_data)
print(new_arr) # array('i', [1, 2, 3])
5.2 tofile()和fromfile()
5.2.1 tofile()
功能:將數組寫入文件
arr = array.array('d', [1.1, 2.2, 3.3])
with open('data.bin', 'wb') as f:
arr.tofile(f)
5.2.2 fromfile()
功能:從文件讀取數組數據
new_arr = array.array('d')
with open('data.bin', 'rb') as f:
new_arr.fromfile(f, 3) # 讀取3個元素
print(new_arr) # array('d', [1.1, 2.2, 3.3])
5.3 byteswap()
功能:交換字節順序(大小端轉換)
arr = array.array('h', [1, 256]) # 0x0001, 0x0100
print(arr.tobytes()) # b'\x01\x00\x00\x01'
arr.byteswap()
print(arr.tobytes()) # b'\x00\x01\x01\x00'
print(arr) # array('h', [256, 1])
6. 特性和性能考慮
6.1 緩沖區接口
array實現了緩沖區協議,可以高效地與其它支持緩沖區接口的對象交互。
arr = array.array('i', [1, 2, 3, 4, 5])
# 使用memoryview訪問緩沖區
mv = memoryview(arr)
print(mv[1:3].tolist()) # [2, 3]
# 修改數據會反映到原數組
mv[2] = 99
print(arr) # array('i', [1, 2, 99, 4, 5])
6.2 性能比較
表2: array與list性能比較(操作100萬個元素)
| 操作 | array('i') | list | 優勢比 |
|---|---|---|---|
| 創建時間 | 0.05s | 0.12s | 2.4x |
| 內存占用 | 4MB | 8MB | 2x |
| 遍歷速度 | 0.03s | 0.05s | 1.7x |
| 求和速度 | 0.02s | 0.08s | 4x |
6.3 類型轉換
# array轉list
arr = array.array('f', [1.1, 2.2, 3.3])
lst = arr.tolist()
print(lst) # [1.1, 2.2, 3.3]
# list轉array
new_arr = array.array('f', lst)
print(new_arr) # array('f', [1.1, 2.2, 3.3])
7. 應用舉例
7.1 處理大型數值數據集示例
import array
import random
import time
# 生成100萬個隨機數
start = time.time()
data = array.array('d', (random.random() for _ inrange(1_000_000)))
print(f"生成array耗時: {time.time()-start:.3f}秒")
# 計算平均值
start = time.time()
mean = sum(data) / len(data)
print(f"計算平均值耗時: {time.time()-start:.4f}秒")
print(f"平均值: {mean:.4f}")
# 內存占用比較
import sys
list_data = list(data)
print(f"array內存占用: {sys.getsizeof(data)/1_000_000:.2f}MB")
print(f"list內存占用: {sys.getsizeof(list_data)/1_000_000:.2f}MB")
7.2 二進制文件處理示例
import array
defsave_sensor_data(filename, data):
"""保存傳感器數據到二進制文件"""
arr = array.array('H', data)
withopen(filename, 'wb') as f:
arr.tofile(f)
defload_sensor_data(filename, count):
"""從二進制文件加載傳感器數據"""
arr = array.array('H')
withopen(filename, 'rb') as f:
arr.fromfile(f, count)
return arr
# 模擬傳感器數據
sensor_data = [100, 105, 110, 115, 120, 118, 116, 114]
# 保存并加載數據
save_sensor_data('sensor.bin', sensor_data)
loaded_data = load_sensor_data('sensor.bin', len(sensor_data))
print("加載的數據:", loaded_data.tolist())
7.3 與NumPy交互示例
雖然array模塊功能有限,但可以輕松轉換為NumPy數組進行高級數值計算:
import array
import numpy as np
# 創建array
arr = array.array('d', [1.1, 2.2, 3.3, 4.4])
# 轉換為NumPy數組
np_arr = np.array(arr)
print("NumPy數組:", np_arr)
# 執行NumPy操作
print("平方:", np.square(np_arr))
print("平均值:", np.mean(np_arr))
# 轉換回array
new_arr = array.array('d', np_arr.tolist())
print("轉換回array:", new_arr)
8. 知識圖譜
9. 學習路線
-
基礎階段:
- 理解array與list的區別
- 掌握類型碼的選擇
- 學習基本的創建和操作方法
-
中級階段:
- 掌握二進制數據交互
- 學習文件讀寫操作
- 理解緩沖區協議
-
高級階段:
- 性能優化技巧
- 與NumPy等庫的交互
- 實際項目應用
-
專家階段:
- 深入理解內存布局
- 與C/C++擴展交互
- 自定義高效數據結構
10. 總結
10.1 核心要點
- array是高效存儲單一類型數據的序列結構
- 通過類型碼指定元素類型,影響內存占用和性能
- 支持所有基本序列操作,以及二進制數據交互
- 內存連續分配,訪問速度快,適合數值計算
10.2 實踐建議
- 選擇最合適的類型碼以節省內存
- 批量操作(extend, fromlist)比循環append更高效
- 使用緩沖區協議實現零拷貝數據共享
- 對于復雜數值計算,考慮轉換為NumPy數組
10.3 注意事項
- 類型必須一致,否則會引發TypeError
- 'u'類型碼已被棄用,應使用'w'
- 文件操作要注意字節順序(大小端問題)
- 與list相比,array不支持多維結構和混合類型
通過合理使用array模塊,可以在處理大量數值數據時獲得顯著的內存和性能優勢,特別是在內存受限或需要高性能計算的場景中。
更新日期:2025-07-25
交流討論:歡迎在評論區留言!
作者簡介:ICodeWR,專注于科技與編程的全棧開發者,定期分享實用編程技巧和項目實戰經驗。持續學習、適應變化、記錄點滴、復盤反思、成長進步。
重要提示:本文主要是記錄自己的學習與實踐過程,所提內容或者觀點僅代表個人意見,只是我以為的,不代表完全正確,不喜請勿關注。

浙公網安備 33010602011771號