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

CodeC TypePython TypeSize
'b'signed charint1
'B'unsigned charint1
'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

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 header

Array 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: