Arrays in Python
By the Syncfusion DevTutorials team · Last updated
The array module: type codes, indexing from both ends, inserting and removing, searching, every array method, enumerate() and the numeric built-ins.
Think about an egg tray.
It holds twelve eggs. Every slot is the same size and the same shape, because every slot holds the same kind of thing. You find the fourth egg by counting along, not by searching.
That is an array: many values of one kind, kept in order, each reachable by its position.
What You Will Learn
In this lesson, you will learn:
- What an array is, and what Python uses instead most of the time
- How to create one, and what the type code means
- How to reach any element, counting from the front or the back
- How to change, add and remove elements
- How to search an array
- The methods an array carries with it
- How
enumerate()gives you the position and the value together - The numeric built-ins you will use on arrays every day
By the end of this lesson, you will be able to build arrays, reach and change any element by position, add and remove values, and use the built-in functions to work out totals, averages, highest and lowest values.
Even though Python programmers usually use lists, understanding arrays helps you learn the core ideas behind indexed collections.
Arrays
Introduction to Arrays
An array is a collection of values of the same type, stored one after another in memory, each identified by a number called its index.
Because every element is the same size, the computer can jump straight to any position without looking at the ones before it. That is why marks[500] is just as fast as marks[0].
Here is that idea in Python. Three marks are held under one name, and marks[0] is the first one, because positions start at 0:
Three marks in one name
from array import array
marks = array("i", [78, 85, 60])
print(marks)
print(marks[0])
print(len(marks))
An array holds many values of the same kind, in order, each reachable by its position.
The entire collection is stored in one variable, and each value can be reached by its position.
Arrays in Python
Here is the part that confuses people coming from other languages.
In Java or C you reach for an array constantly. In Python you almost always use a list instead.
A list does the same job, with no import
marks = [78, 85, 60]
print(marks)
print(marks[0])
print(len(marks))
A list is built in, takes any mix of types, and has more methods. It is what Python programmers use for a collection of marks.
The array module exists for one reason: storing a lot of numbers compactly. An array of a million whole numbers uses far less memory than a list of a million whole numbers, because it stores the raw numbers rather than full Python objects.
The same values, two different costs
import sys
from array import array
list_marks = [78, 85, 60, 92, 45]
array_marks = array("i", [78, 85, 60, 92, 45])
print("List holds:", list_marks)
print("Array holds:", array_marks)
print("Bytes per number in the array:", array_marks.itemsize)
print("Whole array, in bytes:", array_marks.buffer_info()[1] * array_marks.itemsize)
print("List object alone, in bytes:", sys.getsizeof(list_marks))
The array stores five numbers in 20 bytes. The list needs that much just for its own structure, before counting the five number objects it points at.
So: use a list unless you are holding a great many numbers and memory matters. Learn arrays anyway, because the ideas — index, traverse, insert, delete, search — are the same ones every collection uses.
Array Characteristics
An array has a small set of rules, and every one of them shapes how you use it:
| Characteristic | What it means |
|---|---|
| Same type | every element must match the type code |
| Ordered | elements keep the order you put them in |
| Indexed | the first element is at 0 |
| Changeable | you can replace, add and remove elements |
| Compact | the raw numbers are stored, not Python objects |
The "same type" rule is the real difference from a list, and it is enforced:
An array refuses the wrong type
from array import array
marks = array("i", [78, 85])
marks.append(7.5)
TypeError — i means whole numbers, and 7.5 is not one. A list would have accepted it without a word.
Creating Arrays
Importing the array Module
Arrays are not built in. The array module ships with Python, so there is nothing to install.
Two ways to import it
import array
a = array.array("i", [78, 85])
print(a)
from array import array
b = array("i", [60, 92])
print(b)
The second form is what you will usually see, because array.array(...) reads oddly.
Creating Arrays with array()
Making an array is a single call:
array(typecode, values)
The type code is a single letter saying what kind of value the array holds. It is not optional.
The two things an array needs
from array import array
marks = array("i", [78, 85, 60])
print(marks)
print("Type code:", marks.typecode)
print("Bytes each:", marks.itemsize)
An array can start empty and be filled later:
Starting empty
from array import array
marks = array("i")
print("Empty:", marks, len(marks))
marks.append(78)
marks.append(85)
print("Filled:", marks, len(marks))
Integer Arrays
i holds whole numbers, taking 4 bytes each.
Whole numbers
from array import array
marks = array("i", [78, 85, 60, 92])
print(marks)
print("Total:", sum(marks))
print("Highest:", max(marks))
Float Arrays
d holds decimal numbers, taking 8 bytes each. f is the smaller, less precise version.
Decimal numbers
from array import array
averages = array("d", [78.5, 85.25, 60.75])
print(averages)
print("Average of averages:", round(sum(averages) / len(averages), 2))
print("Bytes each:", averages.itemsize)
Putting a whole number into a d array is fine — it is widened, exactly as 7 + 2.5 is:
A whole number in a decimal array
from array import array
averages = array("d", [78.5])
averages.append(85)
print(averages)
Character Arrays
The array module has a type code u for single characters.
An array of characters
from array import array
name = array("u", "Asha")
print(name)
print(name[0])
print(name.tounicode())
Be careful with this one. The u type code is deprecated, which means it still works today but is on its way out of Python. For text, use a plain string, and for a collection of words use a list of strings.
What to use for text instead
name = "Asha"
subjects = ["Maths", "Science", "English"]
print(name[0])
print(subjects[0])
print(len(name), len(subjects))
Strings and lists support the same indexing you are learning here, so nothing is lost.
Array Type Codes
The codes are one letter each, and each letter fixes the size of one element:
| Code | Holds | Bytes | Example |
|---|---|---|---|
b | small whole number, signed | 1 | array("b", [-5, 5]) |
B | small whole number, no minus | 1 | array("B", [0, 255]) |
i | whole number | 2 or more | array("i", [78]) |
I | whole number, no minus | 2 or more | array("I", [78]) |
l | bigger whole number | 4 or more | array("l", [100000]) |
q | very big whole number | 8 | array("q", [10 ** 15]) |
f | decimal, less precise | 4 | array("f", [78.5]) |
d | decimal | 8 | array("d", [78.5]) |
u | one character (deprecated) | 2 or 4 | array("u", "Asha") |
Different codes, different sizes
from array import array
for code in ["b", "i", "l", "q", "f", "d"]:
sample = array(code, [1])
print(code, "->", sample.itemsize, "bytes each")
Choose the smallest code that fits your numbers. A code too small will refuse the value rather than wrap around quietly:
A number too big for its code
from array import array
small = array("b", [127])
small.append(200)
OverflowError — b holds up to 127, and 200 does not fit.
Once an array has been created, the next step is learning how to read values from it.
Accessing Array Elements
Array Indexing
An index is the position of an element. Python counts from 0, so the first element is at index 0.
Positive Indexing
Counting from the front
from array import array
marks = array("i", [78, 85, 60, 92])
print("First:", marks[0])
print("Second:", marks[1])
print("Last:", marks[3])
With four elements, the valid indexes are 0, 1, 2 and 3. The last index is always one less than the length, which is the single most common off-by-one in programming.
One step past the end
from array import array
marks = array("i", [78, 85, 60, 92])
print(marks[4])
IndexError: array index out of range.
Negative Indexing
A negative index counts from the back. -1 is the last element.
Counting from the back
from array import array
marks = array("i", [78, 85, 60, 92])
print("Last:", marks[-1])
print("Second from last:", marks[-2])
print("First:", marks[-len(marks)])
marks[-1] is much safer than marks[len(marks) - 1], and says the same thing.
Slicing works too, taking a range of positions:
Taking a slice
from array import array
marks = array("i", [78, 85, 60, 92, 45])
print(marks[1:3])
print(marks[:2])
print(marks[2:])
print(marks[::-1])
A slice goes up to but not including the second number, exactly like range().
Traversing Arrays
Traversing means visiting every element in turn.
Visiting every element
from array import array
marks = array("i", [78, 85, 60])
for mark in marks:
print("Mark:", mark)
That is the form to reach for. Looping over the indexes is possible, but only worth it when you actually need the position:
Looping over the positions instead
from array import array
marks = array("i", [78, 85, 60])
for position in range(len(marks)):
print(position, "->", marks[position])
Reading values is only half the story. Arrays are mutable, which means you can change their contents after creation.
Modifying Arrays
Updating Array Elements
Assign to a position to replace what is there.
Replacing one element
from array import array
marks = array("i", [78, 85, 60])
print("Before:", marks)
marks[2] = 75
print("After:", marks)
The array did not grow. One value was swapped for another.
Inserting Elements
insert(position, value) puts a value before the given position, and everything after it shifts along.
Inserting in the middle
from array import array
marks = array("i", [78, 85, 60])
marks.insert(1, 100)
print(marks)
100 is now at index 1, and 85 and 60 have each moved one place right.
Inserting at the front
from array import array
marks = array("i", [78, 85])
marks.insert(0, 50)
print(marks)
Inserting at the front is the slowest thing you can do to an array, because every other element has to move. Adding at the end moves nothing.
Appending Elements
append(value) adds one value to the end.
Adding to the end
from array import array
marks = array("i", [78, 85])
marks.append(60)
marks.append(92)
print(marks)
print("Length now:", len(marks))
Removing Array Elements
Using remove()
remove(value) deletes the first element equal to that value. It works by value, not by position.
Removing by value
from array import array
marks = array("i", [78, 85, 60, 85])
marks.remove(85)
print(marks)
Only the first 85 went. The second is still there.
If the value is not present, Python stops:
Removing something that is not there
from array import array
marks = array("i", [78, 85])
marks.remove(99)
ValueError — check with in first when you are not sure.
Using pop()
pop() removes an element by position and hands it back to you.
Removing by position, and keeping the value
from array import array
marks = array("i", [78, 85, 60])
last = marks.pop()
first = marks.pop(0)
print("Removed from the end:", last)
print("Removed from the front:", first)
print("What is left:", marks)
With no number, pop() takes the last element. With a number, it takes that position.
Here are the two side by side, so the difference stands out:
remove() | pop() | |
|---|---|---|
| Works by | value | position |
| Gives back | nothing | the removed element |
| Not found | ValueError | IndexError |
| Use when | you know the value | you know the position, or want the value |
After learning how to add, remove and change values, the next skill is finding them.
Searching in Arrays
Finding Elements with index()
index(value) gives the position of the first element equal to that value.
Finding a position
from array import array
marks = array("i", [78, 85, 60, 85])
print(marks.index(85))
print(marks.index(60))
It raises ValueError when the value is missing, so test first:
Looking before leaping
from array import array
marks = array("i", [78, 85, 60])
if 99 in marks:
print("Found at", marks.index(99))
else:
print("99 is not in the array")
Membership Testing
in answers whether a value is present, with no error and no position.
Just asking whether it is there
from array import array
marks = array("i", [78, 85, 60])
print(78 in marks)
print(99 in marks)
print(99 not in marks)
Use in when you want a yes or no, and index() when you need to know where.
Array Operations
These five operations are what every collection is judged on, in any language.
Traversing
Visiting every element once.
Traversal, and what it costs
from array import array
marks = array("i", [78, 85, 60, 92])
total = 0
for mark in marks:
total += mark
print("Total:", total)
print("Elements visited:", len(marks))
Traversal always costs one step per element.
Insertion
There are two ways to add, and they behave differently:
Insertion at the end and in the middle
from array import array
marks = array("i", [78, 85, 60])
marks.append(92)
print("After append:", marks)
marks.insert(1, 100)
print("After insert at 1:", marks)
Appending is cheap. Inserting near the front means shifting everything after it.
Deletion
Three ways to delete
from array import array
marks = array("i", [78, 85, 60, 92])
marks.remove(85)
print("After remove(85):", marks)
marks.pop(0)
print("After pop(0):", marks)
del marks[0]
print("After del marks[0]:", marks)
del removes by position and gives nothing back, which is the difference from pop().
Search
Searching from front to back
from array import array
marks = array("i", [78, 85, 60, 92])
target = 60
for position, mark in enumerate(marks):
if mark == target:
print("Found", target, "at position", position)
break
else:
print(target, "is not here")
This is a linear search: look at each element until you find it. The worst case checks every element.
Update
Changing one element, and all of them
from array import array
marks = array("i", [78, 85, 60])
marks[0] = 80
print("One changed:", marks)
for position in range(len(marks)):
marks[position] += 5
print("All raised by 5:", marks)
Changing one element is instant — Python jumps straight to that position.
Array Methods
An array carries its own set of methods. To add elements you have three choices, each for a different job.
append()
Adds one element to the end.
append
from array import array
marks = array("i", [78])
marks.append(85)
print(marks)
If you append a tuple or a list, the whole thing is added as one element.
extend()
Adds several elements to the end.
extend, and how it differs from append
from array import array
a = array("i", [78, 85])
a.extend([60, 92])
print("extend:", a)
b = array("i", [78, 85])
b.append(60)
print("append:", b)
append adds one thing. extend adds each item of a collection.
insert()
insert
from array import array
marks = array("i", [78, 60])
marks.insert(1, 85)
print(marks)
remove()
remove
from array import array
marks = array("i", [78, 85, 60])
marks.remove(85)
print(marks)
pop()
pop
from array import array
marks = array("i", [78, 85, 60])
print("Taken:", marks.pop())
print("Left:", marks)
index()
index
from array import array
marks = array("i", [78, 85, 60])
print(marks.index(60))
reverse()
Reverses the array in place — it changes the array and gives nothing back.
reverse changes the array itself
from array import array
marks = array("i", [78, 85, 60])
result = marks.reverse()
print("The array now:", marks)
print("What reverse() returned:", result)
result is None. Writing marks = marks.reverse() would throw the array away — a mistake worth meeting once.
tolist()
Converts the array into an ordinary list.
tolist
from array import array
marks = array("i", [78, 85, 60])
as_list = marks.tolist()
print(as_list, type(as_list).__name__)
as_list.append("absent")
print("A list accepts anything:", as_list)
Use it when you need something a list can do and an array cannot — mixing types, or handing the values to code that expects a list.
Here is the full set in one table:
| Method | What it does | Gives back |
|---|---|---|
append(v) | adds one element at the end | nothing |
extend(values) | adds each item of a collection | nothing |
insert(i, v) | inserts before position i | nothing |
remove(v) | deletes the first element equal to v | nothing |
pop(i) | deletes by position | the removed element |
index(v) | position of the first v | a number |
reverse() | reverses in place | nothing |
tolist() | copies into a list | a new list |
Most array methods change the array and return None. marks = marks.reverse() leaves you holding None with the array gone. Call it on its own line.
enumerate() Function
Getting Index and Value
Often you want both the position and the value. Doing it by hand needs a counter:
Keeping a counter by hand
from array import array
marks = array("i", [78, 85, 60])
position = 0
for mark in marks:
print(position, mark)
position += 1
enumerate() does that for you, and cannot forget to add 1:
enumerate does it for you
from array import array
marks = array("i", [78, 85, 60])
for position, mark in enumerate(marks):
print(position, mark)
Using enumerate() in Loops
start= changes the first number, which is how you number things for people:
Numbering from 1 for a report
from array import array
marks = array("i", [78, 85, 60])
subjects = ["Maths", "Science", "English"]
for number, mark in enumerate(marks, start=1):
print(number, subjects[number - 1], mark)
enumerate() works on anything you can loop over, not just arrays:
The same tool on a string and a list
for position, letter in enumerate("Asha"):
print(position, letter)
for position, subject in enumerate(["Maths", "Science"]):
print(position, subject)
Reach for enumerate() whenever you catch yourself writing range(len(...)). It is shorter, and the counter cannot drift out of step with the values.
Arrays work well with many of Python's built-in numeric functions. These functions can calculate totals, averages and other useful values without writing the loops yourself.
Numeric Functions
These are built in. They work on arrays, lists, and anything else you can loop over.
sum()
sum() adds up everything in a collection:
sum
from array import array
marks = array("i", [78, 85, 60])
print(sum(marks))
print(sum(marks) / len(marks))
print(sum(marks, 100))
The second number is where the total starts, which is occasionally useful and often surprising.
min() and max()
min() and max() find the ends of a collection, and both sides of a comparison:
min and max
from array import array
marks = array("i", [78, 85, 60])
print("Lowest:", min(marks))
print("Highest:", max(marks))
print("Range:", max(marks) - min(marks))
They work on text too, comparing character by character:
min and max on text
subjects = ["Maths", "Science", "English"]
print(min(subjects))
print(max(subjects))
print(max("Asha"))
max("Asha") is s, not A. Capital letters come before small ones in character order, so s is the largest character here.
round()
round
from array import array
averages = array("d", [78.456, 85.5, 60.249])
print(round(78.456, 2))
print(round(sum(averages) / len(averages), 1))
print(round(78.456))
With no second number, round() gives a whole number.
abs()
abs() gives the distance from zero, dropping any minus sign.
abs
marks_change = [-12, 5, -3]
for change in marks_change:
print(change, "-> moved by", abs(change))
Useful whenever you care how much something changed, not which way.
pow()
pow(x, y) is x to the power of y — the same as x ** y.
pow
print(pow(2, 3))
print(2 ** 3)
print(pow(144, 0.5))
print(pow(2, 10, 1000))
The third number is a remainder step, used in cryptography. Treat it as a curiosity for now.
Here are all six in one table:
| Function | What it does | Example | Result |
|---|---|---|---|
sum(values) | adds them up | sum([78, 85]) | 163 |
min(values) | smallest | min([78, 85]) | 78 |
max(values) | largest | max([78, 85]) | 85 |
round(x, n) | rounds to n places | round(78.456, 1) | 78.5 |
abs(x) | distance from zero | abs(-12) | 12 |
pow(x, y) | x to the power of y | pow(2, 3) | 8 |
A small report built from the lot
from array import array
marks = array("i", [78, 85, 60, 92, 45])
print("Count: ", len(marks))
print("Total: ", sum(marks))
print("Average: ", round(sum(marks) / len(marks), 1))
print("Lowest: ", min(marks))
print("Highest: ", max(marks))
print("Spread: ", abs(max(marks) - min(marks)))
Common mistakes
Each row is one mistake. The middle column is what you will actually see on screen.
| Mistake | What you see | Why it happens | Fix |
|---|---|---|---|
| Using the length as the last index | IndexError: array index out of range | The last index is one less than the length | marks[-1], or marks[len(marks) - 1] |
| Putting the wrong type in | TypeError: 'float' object cannot be interpreted as an integer | The type code is enforced | Match the code, or use d for decimals |
| A number too big for its code | OverflowError | b holds up to 127 | Use a wider code such as i or q |
Assigning the result of reverse() | The array becomes None | It changes the array in place and returns nothing | Call it on its own line |
remove() for a value that is absent | ValueError | remove() works by value and needs it present | Check with in first |
Confusing remove() with pop() | The wrong element disappears | remove() takes a value, pop() a position | Pick by what you actually know |
append() where extend() was meant | A collection added as one element | append adds exactly one thing | extend to add each item |
Expecting remove() to delete every copy | Only the first one goes | It removes the first match | Loop, or rebuild the array |
| Forgetting the type code | TypeError: array() argument 1 must be a str | The code is not optional | array("i", [...]) |
| Changing an array while looping over it | Elements quietly skipped | The positions shift under the loop | Loop over a copy, or build a new one |
What to Remember
- An array holds many values of the same kind, in order, each reachable by its position.
- In Python you normally use a list. The
arraymodule is for storing a great many numbers compactly. array(typecode, values)needs the type code, and the code is enforced.- The first index is 0, and the last index is one less than the length.
marks[-1]is the last element. - A slice goes up to but not including its second number.
append()adds one element,extend()adds each item of a collection.remove()works by value and returns nothing;pop()works by position and hands the element back.index()gives a position and raisesValueErrorwhen the value is missing;injust answers yes or no.- Methods that change an array return
None. Never writemarks = marks.reverse(). enumerate()gives the position and the value together — reach for it instead ofrange(len(...)).sum(),min(),max(),round(),abs()andpow()are built in and work on any collection.
Next: String Operations