Show the practical differences between a Python list and a tuple: mutability, available methods and hashability.
A list and a tuple holding the same values compare equal, but they are different types with different capabilities.
values = [1, 2, 3]
frozen = (1, 2, 3)
print(values == frozen) # True - same values
print(type(values).__name__, type(frozen).__name__) # list tuple
values.append(4)
print(values) # [1, 2, 3, 4]
try:
frozen.append(4)
except AttributeError as err:
print("AttributeError:", err)
# Tuples are hashable, lists are not
print(hash(frozen) == hash((1, 2, 3))) # True
try:
{values: "list key"}
except TypeError as err:
print("TypeError:", err)The AttributeError confirms that a tuple has no append method — the mutating methods simply do not exist on it. The dict example shows the second difference: a tuple of hashable values can be a dictionary key, while a list cannot, because it is mutable and its hash would change.
Tuples do have a few methods, just not the mutating ones. count and index work on them, and they support slicing, concatenation and repetition, all of which produce new tuples. They are also smaller and marginally faster to create than the equivalent list, because there is no over-allocation to make room for later appends.
The hashability point deserves a caveat. A tuple is only hashable if all of its contents are hashable, so a tuple containing a list raises a TypeError when you try to hash it. That is the same rule that applies to a frozenset, and it is worth checking when a tuple is used as a dictionary key.