Python Arrays
Learn how to create and use Python arrays with the built-in array module: typecodes, indexing, slicing, mutating elements, and when to prefer arrays over lists.
This chapter covers Python's built-in array module, which provides a compact, type-restricted sequence for storing homogeneous numeric data. You will learn what type codes are, how to create and index arrays, how to mutate them with the full set of available methods, and — crucially — when an array is the right choice over a plain Python list.
What is the array Module?
Python's array module provides a sequence type that stores elements of a single C-compatible numeric type. Unlike a list, which can hold any mix of objects, every slot in an array holds exactly the same kind of primitive value (an integer, a float, etc.). This constraint makes arrays more memory-efficient than lists for large collections of numbers.
Key points:
- Defined in the standard library — no installation required.
- All elements must share the same typecode (a single character that identifies the C type).
- Supports standard sequence operations: indexing, slicing, iteration,
len(), and membership testing within. - Useful when you need compact storage without reaching for a third-party library like NumPy.
If you are already familiar with Python lists, think of an array as a list that trades flexibility for memory efficiency.
Typecodes
Every array is created with a typecode — a one-character string that tells Python which C type to use for each element and therefore how many bytes each slot occupies.
| Typecode | C type | Minimum bytes | Typical use |
|---|---|---|---|
'b' | signed char | 1 | Small integers −128 to 127 |
'B' | unsigned char | 1 | Small non-negative integers 0–255 |
'h' | signed short | 2 | Medium integers |
'H' | unsigned short | 2 | Medium non-negative integers |
'i' | signed int | 2 | General-purpose integers (usually 4 bytes) |
'I' | unsigned int | 2 | Non-negative integers |
'l' | signed long | 4 | Larger integers |
'L' | unsigned long | 4 | Larger non-negative integers |
'q' | signed long long | 8 | Very large integers |
'Q' | unsigned long long | 8 | Very large non-negative integers |
'f' | float | 4 | Single-precision floating point |
'd' | double | 8 | Double-precision floating point |
The actual byte size may vary by platform. Use array.itemsize to inspect it at runtime.
Note on
'u'(Unicode character): This typecode was deprecated in Python 3.3 and removed in Python 3.13. Do not use it in new code — usestrorbytesinstead.
Creating Arrays
Import the module and call array.array(typecode, initializer), where initializer is any iterable of values compatible with the chosen typecode.
import array as arr
# Array of signed integers
int_array = arr.array('i', [1, 2, 3, 4, 5])
print(int_array) # array('i', [1, 2, 3, 4, 5])
# Array of double-precision floats
float_array = arr.array('d', [1.1, 2.2, 3.3])
print(float_array) # array('d', [1.1, 2.2, 3.3])
# Inspect the typecode and bytes-per-element
print(int_array.typecode) # i
print(int_array.itemsize) # 4 (platform-dependent)You can also create an empty array and populate it later:
import array as arr
empty = arr.array('i') # empty integer array
empty.append(10)
empty.append(20)
print(empty) # array('i', [10, 20])Accessing Array Elements
Array indexing works exactly like list indexing: zero-based from the left, and negative indices count from the right.
Accessing an index outside the valid range raises an IndexError, exactly as it does for lists.
Slicing Arrays
Slicing returns a new array of the same typecode containing the selected elements. The syntax is a[start:stop:step] — the same as for lists and strings.
Iterating Over an Array
You can iterate over an array with a for loop, or check membership with in:
import array as arr
a = arr.array('i', [10, 20, 30, 40, 50])
for item in a:
print(item, end=' ')
# Output: 10 20 30 40 50
print()
print(30 in a) # True
print(99 in a) # False
print(len(a)) # 5Modifying Arrays
Arrays are mutable — you can change, add, and remove elements after creation.
Changing an Element
Assign a new value directly to an index:
Adding Elements
Use append() to add a single element at the end, or extend() to add multiple elements from any iterable:
Use insert(index, value) to place an element at a specific position:
import array as arr
a = arr.array('i', [1, 2, 3, 4, 5])
a.insert(2, 10) # insert 10 before index 2
print(a) # array('i', [1, 2, 10, 3, 4, 5])Removing Elements
remove(value) deletes the first occurrence of the given value and raises ValueError if it is not found:
pop(index) removes and returns the element at index (defaults to the last element):
import array as arr
a = arr.array('i', [1, 2, 3, 4, 5])
last = a.pop() # removes and returns 5
print(last) # 5
print(a) # array('i', [1, 2, 3, 4])
second = a.pop(1) # removes and returns element at index 1
print(second) # 2
print(a) # array('i', [1, 3, 4])Searching and Counting
index(value) returns the index of the first occurrence of value (raises ValueError if absent):
import array as arr
a = arr.array('i', [10, 20, 30, 20, 40])
print(a.index(20)) # 1 — first occurrence
print(a.index(30)) # 2count(value) returns how many times value appears:
import array as arr
a = arr.array('i', [1, 2, 2, 3, 2, 4])
print(a.count(2)) # 3
print(a.count(9)) # 0Reversing an Array
reverse() reverses the array in place:
import array as arr
a = arr.array('i', [1, 2, 3, 4, 5])
a.reverse()
print(a) # array('i', [5, 4, 3, 2, 1])Converting Between Arrays and Lists
tolist() converts an array to a standard Python list. To go the other direction, pass a list to array.array():
import array as arr
a = arr.array('i', [1, 2, 3, 4, 5])
# array → list
my_list = a.tolist()
print(my_list) # [1, 2, 3, 4, 5]
print(type(my_list)) # <class 'list'>
# list → array
back = arr.array('i', my_list)
print(back) # array('i', [1, 2, 3, 4, 5])Changing the Element Type
The typecode attribute is read-only. To store the same values under a different type, create a new array using the original as the initializer:
Memory Efficiency: Arrays vs. Lists
The main practical reason to use the array module instead of a list is memory. A list stores references to Python objects; an array stores the raw C values directly.
import array as arr
import sys
n = 1000
my_list = list(range(n))
my_array = arr.array('i', range(n))
print('List size:', sys.getsizeof(my_list), 'bytes')
print('Array size:', sys.getsizeof(my_array), 'bytes')
# Example output (64-bit platform):
# List size: 8056 bytes
# Array size: 4096 bytesFor large datasets (hundreds of thousands of integers), the savings compound significantly. If you need even more capability — vectorized math, multidimensional arrays — consider NumPy.
When to Use arrays vs. Lists
Use the array module when:
- You are storing a large number of homogeneous numeric values (sensor readings, pixel data, network buffers, etc.).
- Memory usage is a concern and you cannot use a third-party library.
- You are reading from or writing to binary files or network sockets (
tofile()/fromfile()methods make this straightforward).
Stick with Python lists when:
- You need to store mixed types or arbitrary objects.
- The collection is small and memory is not a concern.
- You need rich list methods such as
sort()with a key function.
Use NumPy when:
- You need mathematical operations on entire arrays (vectorized arithmetic, matrix algebra, statistics).
- You are working with multidimensional data.
Method Reference
| Method | Description |
|---|---|
append(x) | Add x to the end of the array |
extend(iterable) | Add all elements from iterable to the end |
insert(i, x) | Insert x before index i |
remove(x) | Remove the first occurrence of x |
pop([i]) | Remove and return element at index i (default: last) |
index(x) | Return the index of the first occurrence of x |
count(x) | Return the number of occurrences of x |
reverse() | Reverse the array in place |
tolist() | Convert the array to a Python list |
tofile(f) | Write all items to the open file object f as machine values |
fromfile(f, n) | Read n items from file object f and append to the array |