PythonArrays (array module)

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.

Python
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 float

Because 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)

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 or 4

I

unsigned int

int

2 or 4

l

signed long

int

4 or 8

L

unsigned long

int

4 or 8

q

signed long long

int

8

Q

unsigned long long

int

8

f

float

float

4

d

double

float

8

u

wchar_t

Unicode char

2 or 4

Note
Exact byte sizes for the integer codes depend on the platform’s C compiler, though `q`/`Q` are always 8 bytes. If you need a guaranteed size regardless of platform, check `array('i').itemsize` at runtime rather than assuming.

Python
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/O
Why 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.

Python
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 * itemsize
  • Memory 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 TypeError immediately instead of silently succeeding.

  • Binary interoptobytes() / 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 (arr * 2)

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 (pip install numpy)

Best for

General-purpose collections

Compact 1-D numeric/binary buffers

Numeric computing, data science, ML

Python
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])
array has no math operations
`array` only stores values compactly — it does not add vectorized math, statistics, or linear algebra on top. `+` concatenates two arrays and `*` repeats one, exactly like a list; there is no element-wise addition or multiplication built in.
Tip
For real numeric computing — element-wise math, statistics, linear algebra, multi-dimensional data — NumPy is the standard tool the whole scientific Python ecosystem is built on. Reach for the built-in `array` module only when you specifically need a lightweight, dependency-free, memory-compact 1-D buffer of one numeric type, such as when reading/writing binary files or interfacing with C code, and reach for NumPy for everything else numeric.