Arrays (array module)
Python’s built-in list can hold anything — strings, numbers, other lists, a mix of types all in the same container. That flexibility comes at a memory cost: every item in a list is really a pointer to a separate Python object floating elsewhere in memory. The standard library’s array module offers a leaner alternative for the common case where you have a large sequence of numbers that are all the same type. An array stores raw C-style values packed contiguously in memory, much like an array in C or Java, which makes it considerably more memory-efficient than a list of the same numbers.
Creating an array
array lives in the array module and is constructed with a type code — a single character telling Python what kind of value the array will hold — followed by an iterable of initial values. Every item you put in must match that type.
from array import array
# 'i' means "signed int" - every item must be an int
numbers = array('i', [1, 2, 3, 4, 5])
print(numbers) # array('i', [1, 2, 3, 4, 5])
print(numbers[0]) # 1
print(len(numbers)) # 5
# Mutable, like a list
numbers.append(6)
numbers[0] = 100
print(numbers) # array('i', [100, 2, 3, 4, 5, 6])
# Adding a value of the wrong type raises TypeError
# numbers.append(3.14) # TypeError: integer argument expected, got floatBecause every element must share the declared type, an array behaves much like a list for everyday operations — indexing, slicing, iterating, append, pop, extend, len() — but it enforces that type constraint on every write.
Type Codes
The type code is what tells array how many bytes to reserve per item and how to interpret them. The most commonly used codes are:
Code | C Type | Python Type | Typical Size (bytes) |
|---|---|---|---|
| signed char | int | 1 |
| unsigned char | int | 1 |
| signed short | int | 2 |
| unsigned short | int | 2 |
| signed int | int | 2 or 4 |
| unsigned int | int | 2 or 4 |
| signed long | int | 4 or 8 |
| unsigned long | int | 4 or 8 |
| signed long long | int | 8 |
| unsigned long long | int | 8 |
| float | float | 4 |
| double | float | 8 |
| wchar_t | Unicode char | 2 or 4 |
from array import array
ints = array('i', [1, 2, 3])
floats = array('d', [1.5, 2.25, 3.75])
print(ints.itemsize) # 4 (bytes per item on most platforms)
print(floats.itemsize) # 8
print(ints.tolist()) # [1, 2, 3] - convert back to a plain list
print(floats.tobytes()) # raw bytes, useful for binary I/OWhy Use array Instead of list?
A plain Python list of a million integers stores a million pointers, each referencing a full-blown Python int object elsewhere in memory. An array('i', ...) of the same million integers stores the raw 4-byte integers back-to-back with no per-item object overhead, which can use several times less memory for large numeric sequences.
from array import array
import sys
numbers_list = list(range(1000))
numbers_array = array('i', range(1000))
print(sys.getsizeof(numbers_list)) # much larger
print(sys.getsizeof(numbers_array)) # much smaller, roughly item count * itemsizeMemory efficiency — items are stored compactly as raw bytes, not as boxed Python objects.
Type safety — every item must match the declared type code; mixing types raises a
TypeErrorimmediately instead of silently succeeding.Binary interop —
tobytes()/frombytes()make it easy to read and write raw binary data, e.g. from a file or network socket.
array vs list vs NumPy
array sits between the flexibility of a plain list and the full numeric computing power of a third-party library like NumPy. In practice, most real numeric work reaches for NumPy rather than the standard library array module.
list | array | numpy.ndarray | |
|---|---|---|---|
Element types | Any, mixed freely | One numeric/char type | One dtype (int, float, etc.) |
Memory per element | Full Python object + pointer | Raw fixed-size value | Raw fixed-size value |
Math on whole collection ( | Not supported directly | Not supported | Supported (vectorized) |
Multi-dimensional support | Nested lists only | No (1-D only) | Yes, native |
Dependency | Built-in | Built-in | Third-party ( |
Best for | General-purpose collections | Compact 1-D numeric/binary buffers | Numeric computing, data science, ML |
from array import array
nums = array('i', [1, 2, 3])
# nums * 2 # This repeats the sequence like a list: array('i', [1, 2, 3, 1, 2, 3])
# NumPy (if installed) treats '*' as element-wise math instead:
# import numpy as np
# a = np.array([1, 2, 3])
# print(a * 2) # array([2, 4, 6])