Coding Lists in Programming (Beginner Guide)
A list is an ordered collection of items that your program can access by position. In this guide, you’ll learn how to create lists, read and change their values, add and remove items, and loop through them. You’ll also see how indexing differs across languages, how to avoid common bugs, and when another collection may fit better.
Lists can feel simple until a program skips an item, rejects an index, or changes the wrong value. I find it helps to learn them through small, tested steps rather than memorize commands. The examples below use Python 3, with notes on how lists and similar structures work in other languages.
List Fundamentals: Purpose, Syntax, and Language Differences
A list is an ordered collection: its items keep a sequence, and you can refer to an item by its position. In many languages, lists can grow or shrink as a program runs. The name and rules vary, so check the language before applying an example.
In Python, square brackets create a list:
scores = [82, 91, 76]
names = ["Maya", "Leo"]
empty = []
A list can hold values of different types, though keeping one kind of value is often easier to work with:
items = ["notebook", 3, True]
Most beginner examples use a list of numbers or a list of strings. A list may also contain other lists, creating a nested list.
Lists, arrays, sets, and dictionaries
These structures solve related but different problems:
| Structure | Keeps order? | Access method | Useful when |
|---|---|---|---|
| Python list | Yes | Position, or index | Items may repeat and order matters |
| Set | Not a position-based sequence | Membership check | You need unique items |
| Dictionary | Not accessed by numeric position | Key | Each value belongs to a named key |
| Fixed-size array | Usually ordered | Position, or index | The language or task calls for set-size storage |
In Python, a list is a flexible, indexable sequence. Its implementation uses a dynamic array, which can grow as needed. Other languages use different names and rules. Java’s ArrayList, C#’s List<T>, and C++’s vector are common resizable, indexable collections. A Java array, by contrast, has a fixed length after creation.
A set is a poor fit when you need repeated values or a reliable position for each item. A dictionary is a better fit when you want to look up a value by a label, such as "email", rather than by its place in a sequence.
Indexing across languages
Python uses zero-based indexing: the first item is at index 0, the second at 1, and so on. Common C-family languages, including C, C++, Java, and C#, also use zero-based indexes for arrays and similar collections. Go slices and JavaScript arrays do too.
Not every language follows that rule. R and MATLAB commonly start indexing at 1. Lua tables often use 1 as the first position by convention, though their keys are flexible. Some libraries also provide operations whose rules differ from the language’s usual indexing. Check the documentation for the specific language and API you use.
For a list of length n, valid Python indexes run from 0 through n - 1. That last index is not n:
scores = [82, 91, 76]
print(scores[0]) # 82
print(scores[2]) # 76
Next step: Before using an index, check both where counting starts and how many items the collection contains.
Core Operations, Indexing, and Curriculum Requirements
Core list skills include creating a collection, reading and updating items, adding or removing values, and processing each item in a loop. Practice these with short examples first. Then test how your code behaves when the list is empty, has one item, or receives an index at its boundary.
Read, update, and check a list
Read an item with its index, then assign a new value at that position to update it:
colors = ["blue", "green", "red"]
first_color = colors[0]
colors[1] = "yellow"
Python’s len() function gives the number of items. Use it to check that an index is valid before reading or updating:
index = 2
if 0 <= index < len(colors):
print(colors[index])
else:
print("Index is outside the list")
Reading an invalid index in Python raises an IndexError. Other languages may raise an exception, return a special value, or behave differently. In languages such as C, accessing an array outside its bounds can have unsafe or undefined behavior. Do not rely on invalid access as a way to check a boundary.
An empty list has length zero, so it has no valid indexes. Check that it contains an item before reading its first value:
if colors:
print(colors[0])
Add, insert, remove, and slice
In Python, append() adds an item at the end. insert() adds one at a chosen position. remove() deletes the first matching value, while pop() removes and returns an item by index. With no index, pop() removes the last item.
tasks = ["read", "email"]
tasks.append("plan")
tasks.insert(1, "review")
tasks.remove("email")
last_task = tasks.pop()
These commands change the original list. That change is called mutation. Slicing, by contrast, makes a new list containing part of the sequence:
numbers = [10, 20, 30, 40, 50]
middle = numbers[1:4] # [20, 30, 40]
The slice includes the start index but stops before the end index. So numbers[1:4] selects indexes 1, 2, and 3. A slice such as numbers[:2] starts at the beginning; numbers[2:] continues to the end.
| Task | Python example | Result or detail |
|---|---|---|
| Create | values = [4, 7] |
A list with two items |
| Read | values[0] |
4 |
| Update | values[1] = 8 |
Changes the second item |
| Append | values.append(9) |
Adds at the end |
| Insert | values.insert(1, 6) |
Adds before index 1 |
| Remove by value | values.remove(6) |
Removes first match |
| Remove by index | values.pop(0) |
Removes and returns item |
| Slice | values[0:2] |
Makes a new list of selected items |
Next step: Run each example, print the list after every change, and confirm that the result matches your expectation.
Iterate through every item
A for loop processes the items in order:
for color in colors:
print(color)
When you need each position too, use enumerate():
for index, color in enumerate(colors):
print(index, color)
Avoid removing items from a list while looping over that same list. The positions shift after removal, so the loop may skip an item or produce an incorrect result. A safe beginner pattern is to build a new list:
values = [2, 5, 8, 11]
evens = []
for value in values:
if value % 2 == 0:
evens.append(value)
Here, % gives the remainder after division, so even numbers have a remainder of zero when divided by two. A compact version uses a list comprehension:
evens = [value for value in values if value % 2 == 0]
Use the loop form first if it makes the steps clearer. If you truly need to delete items from the original list, one option is to loop over a copy: for value in values.copy():. Then remove from values inside that loop.
Practice Strategies, Common Errors, and Learning Milestones
A good practice plan moves from basic operations to small problems. Start with known inputs, inspect each result, and test boundary cases. Then explain what the code does and how its work grows as the list gets longer. This builds sound habits without hiding the steps behind advanced syntax.
A short practice sequence
- Review the basics. Make sure you can use variables, data types, conditionals, and loops. Learn the chosen language’s collection syntax.
- Create and inspect. Make lists with zero, one, and several items. Print their lengths and contents.
- Change values. Read an item, update it, append a value, insert a value, remove a value, and slice the list.
- Solve small tasks. Find a maximum, keep only values that meet a rule, or create a new list with duplicates removed.
- Test boundaries. Try an empty list, a single-item list, the first valid index, and the last valid index.
- Explain the result. State what each line changes and what happens when the input is longer.
For example, Python’s max() finds the largest value in a non-empty list:
temperatures = [18, 22, 19]
if temperatures:
highest = max(temperatures)
print(highest)
The check matters because max([]) raises a ValueError. You can also find the maximum with a loop, which gives you practice tracking a changing value.
To remove duplicates while keeping the first occurrence of each value, you can build a result list:
values = [3, 3, 1, 3, 1]
unique = []
for value in values:
if value not in unique:
unique.append(value)
This is easy to read, but membership checks in a list take longer as the list grows. If order does not matter, a set may be a better fit. In Python, list(dict.fromkeys(values)) is another option that keeps insertion order in current Python versions; for beginners, the loop makes the logic more visible.
Common bugs and how to prevent them
An off-by-one error means a position is one step too early or too late. A loop using range(len(values)) visits indexes from 0 to len(values) - 1, because the end of a Python range is excluded:
for index in range(len(values)):
print(values[index])
A loop that tries to read values[len(values)] goes one step past the last item. When you only need the values, loop over the list directly. When you need positions, use enumerate() or check the bounds.
Mutation during iteration is another common source of bugs. Removing an item shifts later items left, but the loop still moves forward. This can cause an item to be skipped. Build a new list or loop over a copy instead.
Milestone: You are ready to move on when you can write a small list program, explain its empty and boundary behavior, and test it with different inputs.
What basic operation costs mean
Big O notation describes how the work of an operation tends to grow as a collection gets larger. For Python lists and other dynamic-array-based collections, indexed access is typically O(1), or constant time. Inserting or deleting near the beginning is typically O(n) because later items may need to shift.
| Operation | Typical cost for a dynamic array | Why |
|---|---|---|
| Read or update by index | O(1) | Jump to a position |
| Search for a value | O(n) | May inspect each item |
| Append at the end | Amortized O(1) | Most appends are quick; occasional resizing costs more |
| Insert or delete near the start | O(n) | Other items may shift |
Make a slice of k items |
O(k) | The selected items are copied |
“Amortized” describes an average across many operations: a single append may involve resizing, but the cost spread across a sequence of appends is typically constant per item. Actual performance depends on the language and its implementation, so treat these as useful patterns, not guarantees for every collection.
Lists in Projects, Further Study, and Career Pathways
Lists are useful in everyday programs that process sequences, such as a set of quiz scores, a queue of tasks, or rows of results. They are a starting point, not a solution for every data problem. Choose a collection based on how you need to find, order, and change its items.
A small project can combine the skills above. For a score summary, store scores in a list, check that it is not empty, calculate a total, and find the highest score:
scores = [82, 91, 76]
if scores:
total = sum(scores)
average = total / len(scores)
highest = max(scores)
print("Average:", average)
print("Highest:", highest)
This works for numeric scores. A more complete program should also decide what to do with invalid input, such as text where a number is expected. That check belongs where data enters the program, before calculations use it.
Another practical task is filtering a list. Given a list of product prices, create a second list containing items below a chosen limit. This teaches iteration, conditionals, and appending without changing the source list.
When a project grows, ask what operations happen most often. If you need fast checks for whether a value exists and do not need duplicates or positions, consider a set. If you need to find a value using a label, consider a dictionary. If you frequently add and remove items at the beginning, look into a queue or another structure designed for that pattern.
As I compare beginner exercises, I look for more than whether the code runs once. A useful solution should explain its assumptions, handle an empty input, and behave correctly at the first and last positions. Those habits matter as much as memorizing method names.
Next step: Build one small program, add tests for empty and single-item input, then describe the cost of its main list operations.
Frequently asked questions
What is a list in programming?
A list is an ordered collection of items that a program can access and often change. The exact rules depend on the language.
Are lists and arrays the same?
Not always. A Python list is resizable and indexable, while a Java array has a fixed length. Some languages use different names for similar structures.
Why do list indexes start at zero?
Many languages use zero-based indexing, so the first item has index 0. Some languages and APIs start at 1, so check their rules.
How do I get the last item in a Python list?
Use values[-1] if the list is not empty. Python supports negative indexes, with -1 meaning the last item.
What happens when I use an invalid index?
The result depends on the language. Python raises IndexError; other languages may raise an exception or have different behavior. Check bounds deliberately.
How do I add an item to a Python list?
Use append(item) to add it at the end, or insert(index, item) to add it at a chosen position.
How do I remove an item from a Python list?
Use remove(value) to delete the first matching value, or pop(index) to delete and return the item at an index.
Why should I avoid changing a list inside a loop over it?
Removing items shifts later positions and can make the loop skip values. Build a new list or loop over a copy.
When should I use a set instead of a list?
Use a set when you need unique values or frequent membership checks, and do not need position-based access or repeated items.
What is the time cost of reading a list item by index?
For a dynamic-array-based list, indexed access is typically O(1). Inserting or deleting near the start is typically O(n).
(This article was written by one of our staff writers, Andrew Kensington. Visit our Meet the Team page.)
