The array module provides compact storage for homogeneous numeric data. It uses less memory than lists and offers fast binary I/O—without requiring NumPy.
Creating Arrays
from array import array
# Create typed array
integers = array('i', [1, 2, 3, 4, 5]) # signed int
floats = array('d', [1.0, 2.5, 3.14]) # double
bytes_arr = array('B', [0, 255, 128]) # unsigned char
print(integers) # array('i', [1, 2, 3, 4, 5])Type Codes
| Code | C Type | Python Type | Size |
|---|---|---|---|
'b' | signed char | int | 1 |
'B' | unsigned char | int | 1 |
'h' | signed short | int | 2 |
'H' | unsigned short | int | 2 |
'i' | signed int | int | 2-4 |
'I' | unsigned int | int | 2-4 |
'l' | signed long | int | 4 |
'L' | unsigned long | int | 4 |
'q' | signed long long | int | 8 |
'Q' | unsigned long long | int | 8 |
'f' | float | float | 4 |
'd' | double | float | 8 |
Memory Efficiency
from array import array
import sys
# Compare memory usage
list_data = list(range(10000))
array_data = array('i', range(10000))
print(f"List: {sys.getsizeof(list_data):,} bytes")
print(f"Array: {sys.getsizeof(array_data):,} bytes")
# List: ~80,000 bytes
# Array: ~40,000 bytes (roughly 2x smaller)Array Operations
from array import array
arr = array('i', [1, 2, 3])
# Append
arr.append(4)
# Extend
arr.extend([5, 6, 7])
# Insert
arr.insert(0, 0)
# Pop
last = arr.pop()
# Remove first occurrence
arr.remove(3)
# Index
idx = arr.index(2)
# Count
count = arr.count(1)
# Reverse
arr.reverse()Slicing
from array import array
arr = array('i', [0, 1, 2, 3, 4, 5])
# Slicing works like lists
print(arr[1:4]) # array('i', [1, 2, 3])
print(arr[::2]) # array('i', [0, 2, 4])
print(arr[::-1]) # array('i', [5, 4, 3, 2, 1, 0])
# Assignment
arr[1:3] = array('i', [10, 20])Binary I/O
Fast reading/writing of binary data:
from array import array
# Write to file
data = array('d', [1.1, 2.2, 3.3, 4.4, 5.5])
with open('data.bin', 'wb') as f:
data.tofile(f)
# Read from file
loaded = array('d')
with open('data.bin', 'rb') as f:
loaded.fromfile(f, 5) # Read 5 elements
print(loaded) # array('d', [1.1, 2.2, 3.3, 4.4, 5.5])Converting To/From Bytes
from array import array
arr = array('i', [1, 2, 3])
# To bytes
raw = arr.tobytes()
print(raw) # b'\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00'
# From bytes
new_arr = array('i')
new_arr.frombytes(raw)
print(new_arr) # array('i', [1, 2, 3])Converting To/From List
from array import array
# From list
arr = array('f', [1.0, 2.0, 3.0])
# To list
lst = arr.tolist()
print(lst) # [1.0, 2.0, 3.0]
print(type(lst)) # <class 'list'>Buffer Protocol
Arrays support the buffer protocol for zero-copy operations:
from array import array
import struct
arr = array('i', [1, 2, 3])
# Get memoryview
mv = memoryview(arr)
print(mv[0]) # 1
# Modify through memoryview
mv[0] = 100
print(arr[0]) # 100
# Use with struct
data = struct.pack('3i', *arr)Byte Swapping
Handle endianness:
from array import array
arr = array('i', [1, 256, 65536])
# Swap byte order
arr.byteswap()
print(arr) # Different values depending on system
# Check if native byte order
import sys
print(sys.byteorder) # 'little' or 'big'Image Data Example
from array import array
def create_grayscale_image(width: int, height: int) -> array:
"""Create grayscale image buffer."""
return array('B', [0] * (width * height))
def set_pixel(img: array, width: int, x: int, y: int, value: int):
"""Set pixel value (0-255)."""
img[y * width + x] = value
def get_pixel(img: array, width: int, x: int, y: int) -> int:
"""Get pixel value."""
return img[y * width + x]
# Create 100x100 image
img = create_grayscale_image(100, 100)
# Draw diagonal line
for i in range(100):
set_pixel(img, 100, i, i, 255)
# Save as raw bytes
with open('image.raw', 'wb') as f:
img.tofile(f)Audio Buffer Example
from array import array
import math
def generate_sine_wave(frequency: float, duration: float,
sample_rate: int = 44100) -> array:
"""Generate sine wave audio samples."""
num_samples = int(duration * sample_rate)
samples = array('h') # 16-bit signed
for i in range(num_samples):
t = i / sample_rate
value = int(32767 * math.sin(2 * math.pi * frequency * t))
samples.append(value)
return samples
# Generate 440Hz tone for 1 second
tone = generate_sine_wave(440, 1.0)
print(f"Generated {len(tone)} samples")
# Could write to WAV file with proper headerArray vs List Performance
from array import array
import time
def benchmark():
size = 1_000_000
# List creation
start = time.perf_counter()
lst = list(range(size))
list_time = time.perf_counter() - start
# Array creation
start = time.perf_counter()
arr = array('i', range(size))
array_time = time.perf_counter() - start
print(f"List creation: {list_time:.3f}s")
print(f"Array creation: {array_time:.3f}s")
# Iteration (similar speed)
start = time.perf_counter()
sum(lst)
list_sum_time = time.perf_counter() - start
start = time.perf_counter()
sum(arr)
array_sum_time = time.perf_counter() - start
print(f"List sum: {list_sum_time:.3f}s")
print(f"Array sum: {array_sum_time:.3f}s")
benchmark()When to Use array
Use array when:
- Storing large amounts of homogeneous numeric data
- Memory is constrained
- Reading/writing binary files
- Interfacing with C code via buffer protocol
- You don't need NumPy's features
Use list when:
- Mixed types needed
- Small data sets
- Frequent insertions/deletions in middle
- Simplicity matters more than memory
Use NumPy when:
- Mathematical operations on arrays
- Multi-dimensional arrays
- Broadcasting and vectorization needed
- Scientific computing
The array module hits the sweet spot between Python lists and NumPy arrays—efficient storage for simple numeric sequences without external dependencies.
React to this post: