Working with Dictionaries: Keys and Values
Lists are mutable and the default choice for most tasks; tuples are immutable and solve specific problems.
A Choice with Consequences
When Python needs to hold several related values, lists and tuples are both possible choices. The important difference is what happens after the collection is created. A list can be changed, while a tuple cannot be changed. That difference can make a list convenient for one task and risky for another.
Start with a list when the collection must grow, shrink, or have its elements changed. Choose a tuple when preventing changes solves a specific problem.
Tracing a Mutation
What do you think happens?
What should happen when a program adds an item to a list?
Reveal answer
Answer: The item is added and the collection changes.
Lists are mutable, so elements can be added, removed, or changed after the list is created.
["read", "write", "review"]The list has changed because the task required a collection that could grow. This is a useful form of mutability: a program can accumulate results, build a collection of inputs, filter data, or sort a collection in place.
Mutable Lists and Immutable Tuples
Mutability means that a collection can be changed after creation. Lists are mutable: their elements can be added, removed, or changed. Tuples are immutable: once created, their contents cannot be modified. Python therefore permits a modification operation on a list but stops a corresponding operation on a tuple with an error.
The different outcomes are intentional. A list is appropriate when later updates are part of the task. A tuple is appropriate when the values should remain fixed, because immutability prevents later modification rather than allowing it silently.
Three Reasons to Reach for a Tuple
Selecting a Sequence Type
Choose a list or tuple for each task: a collection that grows during a loop, a fixed pair used as a dictionary key, and several values returned from a function.
Growing collection: Use a list because the task requires adding items while the program runs.
Dictionary key: Use a tuple because dictionary keys must be immutable. A tuple satisfies that requirement.
Multiple return values: Use a tuple because tuples provide cleaner syntax for returning multiple values from a function.
Use a list for a changing collection. Use a tuple for a dictionary key or for a fixed group of values returned together.
Tuples are especially useful in three situations. First, dictionaries require immutable keys, so a tuple can be used as a key while a mutable list cannot. Second, tuples provide cleaner syntax when a function returns multiple values. Third, passing a tuple to a function guarantees that the function cannot modify the original tuple data, which helps prevent aliasing bugs.
In the first example, the tuple groups related values into one dictionary key. In the second, the function returns two related values together using tuple syntax. These are not merely stylistic alternatives to lists: immutability provides a specific guarantee in each case.
Choosing Under Constraints
- Ask whether the collection must be updated after creation.
- If items must be added, removed, or changed, choose a list.
- If changes must be prevented, consider a tuple.
- If the values must form a dictionary key, choose a tuple.
- If a function returns several related values or must receive protected sequence data, consider a tuple.
| Requirement | Appropriate choice | Reason |
|---|---|---|
| Add, remove, or change elements | List | Lists are mutable. |
| Use the sequence as a dictionary key | Tuple | Dictionary keys must be immutable. |
| Return several related values | Tuple | Tuples provide cleaner multiple-value return syntax. |
| Prevent a function from modifying the original sequence | Tuple | Passing a tuple prevents modification of the original tuple data. |
| Store fixed data | Tuple | The tuple cannot be modified after creation. |
Mistakes in Type Selection
Using a tuple for a collection that must grow during a loop.
The task requires adding items, but tuples are immutable.
Fix:
Use a list for a collection that must be built or updated.Using a list when the values must be a dictionary key.
Dictionary keys must be immutable.
Fix:
Represent the fixed pair as a tuple.Choosing a list simply because it is familiar.
A mutable collection does not communicate or guarantee that the data is protected from modification.
Fix:
Use a tuple when preventing modification is part of the task.Treating mutability as universally beneficial.
Unwanted changes can create harder-to-debug problems.
Fix:
Treat immutability as a deliberate protection when the data should not change.
Decision Practice
Choose list or tuple for each situation, then explain which requirement made the decision: (1) a set of values will never change, (2) a program must add and remove items, (3) a sequence must be used as a dictionary key, (4) a function returns several related values, and (5) a function must receive sequence data that it cannot modify.
Hints
- Ask whether the sequence must change after creation.
- Remember that dictionary keys must be immutable.
- Consider whether a tuple would make a multiple-value return cleaner or prevent modification.
Suggested answers: tuple, list, tuple, tuple, and tuple. The reason is not that tuples are always better; each tuple choice follows from a need for fixed data, an immutable dictionary key, cleaner multiple-value returns, or protection from modification.
The Deliberate Choice
- Lists are mutable and are the default choice for most tasks because they can grow, shrink, and change.
- Tuples are immutable, so they are useful when data must remain fixed.
- Use tuples as dictionary keys because dictionary keys must be immutable.
- Tuples provide cleaner syntax for returning multiple values from a function.
- Passing a tuple can prevent a function from modifying the original data and help avoid aliasing bugs.
Key Takeaways
- Choose a list when updates are required.
- Choose a tuple when preventing changes solves a real problem.
- Tuples are appropriate for immutable dictionary keys, clean multiple-value returns, and protected function inputs.
- The right sequence type depends on the task's constraints, not on a universal rule that one type is always better.