Tuples: Immutable Sequences
Tuples are like lists, but immutable โ once created, they can't be changed. This makes them safer for data that shouldn't be modified, and they're slightly faster than lists.
# Creating tuples
empty = ()
single = (42,) # Note the comma โ (42) is just 42 in parentheses!
point = (10, 20)
rgb = (255, 128, 0)
person = ("Alice", 30, "NYC")
# Parentheses are optional
point = 10, 20
a, b = 1, 2 # This is tuple packing and unpacking
# Tuples support indexing and slicing (like lists)
point[0] # 10
point[-1] # 20
point[:] # (10, 20)
# But NOT modification
# point[0] = 100 # TypeError: 'tuple' object does not support item assignmentWhy Use Tuples?
- Return multiple values from functions:
return min_val, max_val - Dictionary keys: lists can't be dict keys, tuples can
- Fixed data: coordinates, RGB colors, database records
- Unpacking: clean multiple assignment
# Tuple unpacking โ very Pythonic
x, y = 10, 20
first, *rest = (1, 2, 3, 4, 5) # first=1, rest=[2,3,4,5]
a, b, c = "xyz" # Works on any iterable
# Swap variables (uses tuple packing/unpacking)
a, b = b, a # Clean swap with no temp variable
# Named coordinates as tuple keys
distances = {(0, 0): 0, (3, 4): 5, (1, 1): 1.41}
distances[(3, 4)] # 5
# Unpacking in for loops
points = [(1, 2), (3, 4), (5, 6)]
for x, y in points:
print(f"Point: ({x}, {y})")namedtuple
from collections import namedtuple
# Create a tuple subclass with named fields
Point = namedtuple('Point', ['x', 'y'])
Color = namedtuple('Color', ['r', 'g', 'b'])
p = Point(10, 20)
print(p.x, p.y) # 10 20 โ named access
print(p[0]) # 10 โ index access still works
print(p) # Point(x=10, y=20)
c = Color(255, 128, 0)
print(c.r) # 255
# Named tuples are immutable like regular tuples
# p.x = 99 # AttributeError
# Convert to dict
p._asdict() # {'x': 10, 'y': 20}
# Create new instance with one field changed
p2 = p._replace(x=99) # Point(x=99, y=20)The collections Module
Python's collections module provides powerful specialized container types beyond the built-ins.
Counter
from collections import Counter
# Count element frequencies
text = "the quick brown fox jumps over the lazy fox"
word_freq = Counter(text.split())
# Counter({'the': 2, 'fox': 2, 'quick': 1, ...})
# Most common elements
word_freq.most_common(3)
# [('the', 2), ('fox', 2), ('quick', 1)]
# Arithmetic operations
c1 = Counter(['a', 'b', 'a', 'c'])
c2 = Counter(['b', 'b', 'c', 'd'])
c1 + c2 # {'a': 2, 'b': 3, 'c': 2, 'd': 1}
c1 - c2 # {'a': 2} โ subtract (drop zeros and negatives)OrderedDict
from collections import OrderedDict
# In Python 3.7+, regular dicts maintain insertion order
# OrderedDict has additional ordering operations
od = OrderedDict()
od["first"] = 1
od["second"] = 2
od["third"] = 3
od.move_to_end("first") # Move to end
od.move_to_end("third", last=False) # Move to beginning
# Still useful for: two OrderedDicts with same content compare equal
# regardless of insertion order in regular dictsdeque
from collections import deque
# Double-ended queue โ O(1) append/pop from both ends
d = deque([1, 2, 3, 4, 5])
d.appendleft(0) # deque([0, 1, 2, 3, 4, 5])
d.popleft() # 0, deque([1, 2, 3, 4, 5])
d.rotate(2) # deque([4, 5, 1, 2, 3]) โ rotate right by 2
# maxlen โ sliding window
window = deque(maxlen=3)
for n in range(7):
window.append(n)
print(list(window))
# [0] โ [0,1] โ [0,1,2] โ [1,2,3] โ [2,3,4] โ [3,4,5] โ [4,5,6]Key Takeaways
- Tuples for fixed data: coordinates, records, dict keys โ where mutation is wrong
- namedtuple: readable tuple fields โ like a lightweight class
- Counter: frequency counting made trivial
- defaultdict: automatic default values for missing keys
- deque: efficient queue and sliding window operations
Practice Exercises
- Create a
namedtuplecalledStudentwith fields name, age, gpa. Create 3 students and sort them by gpa. - Use
Counterto find the 10 most common characters (excluding spaces) in a paragraph of text. - Use a
dequewith maxlen=5 to implement a "recent history" tracker โ a list of the 5 most recently seen items. - Write a function that uses
Counterto check if one string is an anagram of another.