Tuples
Fixed records, unpacking, and why the comma is what makes a tuple.
What you will be able to do
- Create tuples correctly, including the empty and single-element cases
- Index, slice, and iterate a tuple the same way you would a list
- Explain what tuple immutability does and does not protect
- Unpack a tuple into variables, including extended unpacking with *
- Return several values from a function and unpack them at the call site
- Use a tuple as a dictionary key, and say why a list cannot be one
- Choose between a tuple and a list from what the data represents
The idea, in plain English
A tuple is an ordered collection, like a list, with one difference that changes everything about how it is used: you cannot change it after you make it. No append, no remove, no assigning to an index. What you built is what you have.
That sounds like a limitation and is mostly a signal. A list says "this collection will grow and shrink". A tuple says "these values belong together and the shape is fixed". (17.3850, 78.4867) is one location with two parts, not a collection of two numbers you might add a third to. Reading a tuple in someone else code tells you the shape is settled.
The feature you will use constantly is unpacking - pulling a tuple apart into named variables in one line. `name, score, course = student` is the whole of it, and once you see it you start noticing tuples everywhere: every function that returns two things, every loop over enumerate() or zip(), every row a database driver hands back.
Two things trip people up, and both are worth learning now rather than debugging later. The comma is what creates a tuple, not the brackets - so ("Python") is a plain string. And immutability is one level deep, exactly like the shallow copy in lesson 16: a tuple holding a list still lets you change that list.
Worked example: Reading database rows into named variables, one row at a time.
The comma makes the tuple
This is the rule that explains every confusing tuple result you will ever get. Parentheses group things - that is their job everywhere else in Python, as in (2 + 3) * 4. What creates a tuple is the comma.
So `numbers = 10, 20, 30` is a perfectly good tuple with no brackets at all, and `value = (10)` is just the integer 10 wrapped in redundant brackets. To make a one-element tuple you need the comma to do the work: `(10,)`.
The single-element case is where this actually bites, because it fails quietly. `roles = ("admin")` gives you the string "admin", so len(roles) is 5, `"a" in roles` is True, and looping over it yields five characters. Every one of those is a plausible-looking wrong answer.
Write the parentheses anyway. They are optional but they make the intent obvious, and they are required when a tuple appears inside a function call, where a bare comma would read as an argument separator.
(10)An int. The brackets only group - there is no comma.(10,)A one-element tuple. The trailing comma is doing all the work.10, 20, 30A three-element tuple. Parentheses are optional here.()The empty tuple. The one case with no comma. tuple() is the same.("Python")The string "Python" - a classic silent bug.("Python",)A tuple holding one string.Watch out: len(("Python")) is 6 and len(("Python",)) is 1. If a length looks like a character count, you have lost a comma.
Immutable means the structure, not the contents
A tuple will not let you replace, add, or remove an element. data[0] = 100 raises TypeError, and there is no append, no remove, no sort - those methods simply do not exist on a tuple.
What immutability actually fixes is the set of references the tuple holds. It does not reach inside them. If one of those references points at a list, that list is still a list and still mutable.
So with `data = ([1, 2], [3, 4])`, the assignment data[0] = [5, 6] fails, but data[0].append(3) succeeds and leaves you with ([1, 2, 3], [3, 4]). Nothing has gone wrong - the tuple still holds the same two list objects it always did. One of them just has different contents.
This is the same one-level rule as .copy() in lesson 16, and it matters for the same reason: a tuple of immutable values is genuinely fixed, while a tuple containing lists only looks that way.
data[0]Reading is always fine.data[1:3]Slicing is fine - it returns a new tuple.data + otherFine. Builds a new tuple; the originals are untouched.data[0] = xTypeError. You cannot rebind an element.data.append(x)AttributeError. Tuples have no mutating methods at all.data[0].append(x)Works, if data[0] is a list. The tuple is unchanged - the list is not.Unpacking, and the idioms built on it
Unpacking assigns each element of a tuple to its own name in one statement: `name, score, course = student`. The counts have to match exactly, or Python raises ValueError and tells you how many values it got.
Swapping two variables falls straight out of it. `a, b = b, a` works because Python builds the tuple (b, a) from the current values first, then unpacks it - so no temporary variable is needed and nothing is overwritten halfway through.
When the count is not fixed, a starred name absorbs the rest: `first, *middle, last = numbers` gives you the ends and everything between them. The starred name always becomes a list, even when it collects nothing, and you can have at most one of them.
The reason this matters more than it first appears is that Python hands you tuples constantly. enumerate() yields (index, value). zip() yields one tuple per position. A database driver yields one tuple per row. Every `for index, course in enumerate(courses)` you write is tuple unpacking.
a, b, c = dataExact match. Three values, three names, or ValueError.a, b = b, aThe swap idiom. The right side is packed before anything is assigned.first, *rest = dataHead and tail. rest is a list, and is [] if there is nothing left.first, *middle, last = dataBoth ends. Needs at least two values.*start, last = dataThe starred name can come first.for name, score in pairs:Unpacking in a loop header - each element is taken apart as it arrives.Tip: Use _ for a value you do not need: `_, name, _ = row` documents that you deliberately skipped two fields.
Returning several values, and reading rows
A Python function returns one object, but `return total, highest, lowest` packs three into a tuple on the way out, and the caller unpacks it on the way in. The parentheses are absent, so it does not look like a tuple at either end - but type(result) confirms it is one.
That is why multiple return values feel native in Python when they need a special mechanism in many other languages. There is no special mechanism. It is packing and unpacking.
The same shape covers rows of data. A database driver returns each row as a tuple, in column order, so `for user_id, name, email in rows:` is both the idiomatic way to read them and self-documenting about what each column is.
One caution as the tuple grows: past three or four fields, positions get hard to remember and a wrong order is a silent bug rather than an error. At that point reach for a dictionary, or later a dataclass or NamedTuple, where the fields have names.
Tuples as dictionary keys
A dictionary key has to be hashable, which in practice means its hash must never change while it is in use. If a key could change after insertion, the dictionary would be looking in the wrong place for it afterwards.
That rules lists out entirely - `{[1, 2]: "x"}` raises TypeError: unhashable type: list. A tuple of hashable values is fine, which makes it the standard way to key something by a combination of things: a coordinate pair, a (tenant_id, user_id) cache key, a (row, column) cell.
The rule follows the same one-level logic as everything else in this lesson. (1, 2) is hashable. ([1, 2], 3) is not, because it holds a list - a tuple is only as hashable as its contents.
Tip: A composite cache key is the everyday version of this: cache[(user_id, course_id)] needs no string formatting and cannot collide by accident.
Syntax and examples
courses = ("Python", "React", "Node.js")
print(courses[0]) # Python
print(len(courses)) # 3
# Parentheses are optional - the comma is what matters
numbers = 10, 20, 30
print(numbers) # (10, 20, 30)
print(type(numbers)) # <class 'tuple'>
# Mixed types are fine, as in a list
data = (100, "Python", True, 10.5)
# The single-element trap
value = (10)
print(type(value)) # <class 'int'> <- not a tuple
value = (10,)
print(type(value)) # <class 'tuple'>
# The same trap with a string, which is worse because it looks plausible
role = ("admin")
print(len(role)) # 5 <- characters
role = ("admin",)
print(len(role)) # 1 <- one element
# Empty tuples - the one case that needs no comma
empty = ()
print(type(empty), len(empty)) # <class 'tuple'> 0
print(tuple() == ()) # Truecourses = ("Python", "React", "Node.js")
print(courses[0]) # Python
print(courses[-1]) # Node.js - counting back from the end
numbers = (10, 20, 30, 40, 50)
print(numbers[1:4]) # (20, 30, 40) - stop is excluded
print(numbers[:3]) # (10, 20, 30)
print(numbers[2:]) # (30, 40, 50)
print(numbers[::2]) # (10, 30, 50) - every second one
print(numbers[::-1]) # (50, 40, 30, 20, 10) - a new, reversed tuple
# Every slice gives back a tuple, never a list
print(type(numbers[1:4])) # <class 'tuple'>
# + and * build new tuples, exactly as they do for lists
print((1, 2) + (3, 4)) # (1, 2, 3, 4)
print((1, 2) * 3) # (1, 2, 1, 2, 1, 2)
# Membership and comparison work the same way too
print("Python" in courses) # True
print("Java" not in courses) # True
print((1, 2, 3) == (1, 2, 3)) # True
print((1, 2, 3) == (3, 2, 1)) # False - order counts
# The only two methods a tuple has
numbers = (10, 20, 10, 30, 10)
print(numbers.count(10)) # 3
print(numbers.index(20)) # 1
# numbers.index(99) -> ValueErrorcourses = ("Python", "React", "Node.js")
# courses[1] = "Angular" -> TypeError: does not support item assignment
# courses.append("Go") -> AttributeError: no attribute 'append'
# courses.remove("React") -> AttributeError: no attribute 'remove'
# To change one, build a new one
courses = courses + ("Go",) # note the comma - ("Go") would be a string
print(courses) # ('Python', 'React', 'Node.js', 'Go')
# Or convert, edit, convert back
editable = list(courses)
editable.append("Rust")
courses = tuple(editable)
print(courses)
# Immutability is one level deep
data = ([1, 2], [3, 4])
# data[0] = [10, 20] -> TypeError: the tuple will not rebind
data[0].append(3) # but the list inside is still a list
print(data) # ([1, 2, 3], [3, 4])
# A tuple of immutable values really is fixed all the way down
settings = ("localhost", 5432, True)student = ("Chandu", 90, "Python")
name, score, course = student
print(name, score, course) # Chandu 90 Python
# The counts must match exactly
data = (10, 20, 30)
# a, b = data -> ValueError: too many values to unpack
# a, b, c, d = data -> ValueError: not enough values to unpack
# Swapping, with no temporary variable
a, b = 10, 20
a, b = b, a
print(a, b) # 20 10
# The right side is packed into (20, 10) first, then unpacked.
# Extended unpacking - the starred name is always a list
numbers = (1, 2, 3, 4, 5)
first, *middle, last = numbers
print(first, middle, last) # 1 [2, 3, 4] 5
first, second, *remaining = (1, 2, 3, 4, 5, 6)
print(remaining) # [3, 4, 5, 6]
*beginning, second_last, last = (1, 2, 3, 4, 5)
print(beginning) # [1, 2, 3]
# It collects an empty list quite happily
first, *remaining = (1,)
print(first, remaining) # 1 []
# Skip what you do not need
_, name, _ = ("ST101", "Ravi", 85)
print(name) # Ravidef calculate_scores(scores):
return sum(scores), max(scores), min(scores)
total, highest, lowest = calculate_scores([80, 90, 75, 95])
print(total, highest, lowest) # 340 95 75
# There is no special mechanism here - it is just a tuple
result = calculate_scores([80, 90, 75, 95])
print(result) # (340, 95, 75)
print(type(result)) # <class 'tuple'>
# A status-plus-data return
def authenticate(token):
if token == "valid":
return True, "Authentication successful"
return False, "Token rejected"
success, message = authenticate("valid")
print(success, message) # True Authentication successful
# Rows come back as tuples, in column order
rows = [
(1, "Ravi", "ravi@example.com"),
(2, "Anita", "anita@example.com"),
]
for user_id, name, email in rows:
print(user_id, name, email)
# 1 Ravi ravi@example.com
# 2 Anita anita@example.com
# enumerate and zip hand you tuples too - you have been unpacking all along
courses = ["Python", "React"]
print(list(enumerate(courses))) # [(0, 'Python'), (1, 'React')]
for index, course in enumerate(courses, start=1):
print(index, course) # 1 Python / 2 React
names = ["Ravi", "Anita", "Chandu"]
scores = [85, 92, 88]
for name, score in zip(names, scores):
print(name, score)# Any iterable converts
print(tuple(["Python", "React"])) # ('Python', 'React')
print(list(("Python", "React"))) # ['Python', 'React']
print(tuple("Python")) # ('P', 'y', 't', 'h', 'o', 'n')
print(tuple(range(1, 6))) # (1, 2, 3, 4, 5)
# A tuple key is stable, so a dictionary can rely on it
locations = {
(17.3850, 78.4867): "Hyderabad",
(12.9716, 77.5946): "Bengaluru",
}
print(locations[(17.3850, 78.4867)]) # Hyderabad
# A list cannot be a key, because it could change after insertion
# locations[[17.3850, 78.4867]] = "x" -> TypeError: unhashable type: 'list'
# A tuple is only as hashable as what it holds
print(hash((1, 2))) # fine
# hash(([1, 2], 3)) -> TypeError: unhashable type: 'list'
# The everyday use - a composite cache key
cache = {}
cache[(101, "PY101")] = "enrolled"
print(cache[(101, "PY101")]) # enrolled
# Nested tuples index twice
data = (("Ravi", 85), ("Anita", 92))
print(data[0]) # ('Ravi', 85)
print(data[0][1]) # 85Tip: A tuple in a function call needs its parentheses: f((1, 2)) passes one tuple, while f(1, 2) passes two arguments.
Watch out: A trailing comma after a single value turns it into a tuple, even by accident. `total = count,` makes a one-element tuple, which is a real and confusing bug.
Everything a tuple supports
All of it is read-only. Anything that would change the tuple simply does not exist.
items[i]Index, from 0. Negative counts back from the end.
courses[-1]
items[a:b:c]Slice. Always returns a new tuple.
numbers[::-1]
len(items)How many elements.
len(courses)
in / not inMembership. Scans the tuple, so O(n).
"Python" in courses
+Concatenate into a new tuple. Tuple on both sides.
(1, 2) + (3,)
*Repeat the elements into a new tuple.
(1, 2) * 3
==, <, >Same rules as lists - order matters, comparison is lexicographic.
(1, 2) < (1, 3)
count(x)How many elements equal x.
numbers.count(10)
index(x)Position of the first match. ValueError if absent.
courses.index("React")tuple(x) / list(x)Convert either way. Used to edit a tuple and rebuild it.
tuple(["a", "b"])
hash(items)Works only if every element is itself hashable.
hash((1, 2))
List against tuple
The honest one-line version: a list is a collection you expect to change, a tuple is a record whose shape is fixed.
MutableList yes, tuple no. This is the only real difference; everything else follows from it.
Ordered, indexed, sliceableBoth. Duplicates are allowed in both.
append, remove, sort, reverseList only. A tuple has no mutating methods.
count, indexBoth.
Usable as a dictionary keyTuple only, and only when its contents are hashable. Never a list.
Typical useList for a collection that grows; tuple for a fixed record, a coordinate, a multiple return.
Signals to the reader"This will change" against "this shape is settled". That signal is most of the value.
Try it yourself
The code does not change. Swap the content string and the program does something else entirely.
“Set role = ("admin") and print type(role), len(role), and loop over it. Then add the comma and do the same. Say out loud why the first version printed five things.”
“Build data = ([1, 2], [3, 4]). Try data[0] = [9, 9], then try data[0].append(9). Explain why one raises and the other does not.”
“Try a, b = (10, 20, 30) and read the error message carefully - it tells you exactly how many values it found. Then fix it two ways: with three names, and with a starred name.”
“Swap two variables with a, b = b, a. Then try to do it in two separate statements (a = b, then b = a) and work out why that version loses a value.”
“Print list(enumerate(["a", "b"])) and list(zip([1, 2], ["x", "y"])). Look at the brackets in the output and name what is inside the list.”
What usually goes wrong
Parentheses group; the comma creates the tuple. Without it you get whatever was inside - and if that is a string, it will iterate, have a length, and support `in`, so nothing complains.
✗ roles = ("admin")
print(len(roles)) # 5 - it is a string✓ roles = ("admin",)
print(len(roles)) # 1 - a tupleThere is no append, remove, or item assignment. If the data needs to change, either it should have been a list, or you build a new tuple.
✗ courses = ("Python", "React")
courses.append("Node.js")
# AttributeError: no attribute 'append'✓ courses = courses + ("Node.js",)
# or, for several edits:
editable = list(courses)
editable.append("Node.js")
courses = tuple(editable)The tuple fixes which objects it holds, not what those objects contain. A tuple of lists is not a frozen structure.
✗ data = ([1, 2], [3, 4])
data[0].append(5)
print(data) # ([1, 2, 5], [3, 4]) - it changed✓ data = ((1, 2), (3, 4))
# now nothing inside can change eitherThe counts must match exactly. ValueError is raised at the moment of assignment, and the message tells you how many values were actually there.
✗ data = (10, 20, 30)
a, b = data
# ValueError: too many values to unpack (expected 2)✓ a, b, c = data
# or, when the length varies:
a, *rest = dataA key must hash to the same value for as long as it is in the dictionary. A list could change, so Python refuses it outright.
✗ coordinates = [17.3850, 78.4867]
locations = {coordinates: "Hyderabad"}
# TypeError: unhashable type: 'list'✓ coordinates = (17.3850, 78.4867)
locations = {coordinates: "Hyderabad"}The choice should come from the data. If the collection will grow or shrink, a tuple only means you will convert it to a list later and back again.
✗ students = ("Ravi",)
students = students + ("Anita",) # rebuilding on every add✓ students = ["Ravi"]
students.append("Anita")Best practices
- Write the parentheses even when they are optional - they show the reader that a tuple was intended.
- Never leave a single-element tuple without its trailing comma, and read length errors as a missing-comma clue.
- Choose a tuple when the number of fields is fixed and the values belong together; choose a list when the collection changes.
- Unpack into named variables rather than indexing by position - name, score = student beats student[0] and student[1].
- Use _ for fields you are deliberately ignoring, so the reader knows it was a choice.
- Past three or four fields, move to a dictionary, a NamedTuple, or a dataclass - positional meaning stops being readable.
- Use a tuple for a composite dictionary key instead of joining values into a string.
- If you need a fully frozen structure, make sure the elements are immutable too.
Practice
Write these yourself before opening anything. Getting them wrong first is most of how this sticks.
Create a tuple of ("Python", "JavaScript", "TypeScript", "React"). Print the first element, the last element, the length, the tuple reversed, and whether "Python" is in it.
Show hintHide hint
Negative indexing gives you the last element; a slice with a step of -1 reverses.
Show solutionHide solution
languages = ("Python", "JavaScript", "TypeScript", "React")
print(languages[0]) # Python
print(languages[-1]) # React
print(len(languages)) # 4
print(languages[::-1]) # ('React', 'TypeScript', 'JavaScript', 'Python')
print("Python" in languages) # TrueUnpack student = ("Ravi", 90, "Python") into name, score, and course, then print all three.
Show hintHide hint
One assignment statement, three names on the left.
Show solutionHide solution
student = ("Ravi", 90, "Python")
name, score, course = student
print(name) # Ravi
print(score) # 90
print(course) # PythonFrom numbers = (10, 20, 30, 40, 50), use extended unpacking to get first = 10, middle = [20, 30, 40], and last = 50.
Show hintHide hint
One starred name between two ordinary ones.
Show solutionHide solution
numbers = (10, 20, 30, 40, 50)
first, *middle, last = numbers
print(first) # 10
print(middle) # [20, 30, 40] <- a list, not a tuple
print(last) # 50Write calculate(a, b) returning the sum, the difference, and the product. Call it with 10 and 5 and unpack the three results.
Show hintHide hint
Return the three values separated by commas - Python packs them for you.
Show solutionHide solution
def calculate(a, b):
return a + b, a - b, a * b
total, difference, product = calculate(10, 5)
print(total) # 15
print(difference) # 5
print(product) # 50
print(type(calculate(10, 5))) # <class 'tuple'>Convert courses = ["Python", "React", "FastAPI"] to a tuple, then try to modify it and observe the error.
Show hintHide hint
tuple() converts. Then attempt an item assignment and read what Python says.
Show solutionHide solution
courses = ["Python", "React", "FastAPI"]
frozen = tuple(courses)
print(frozen) # ('Python', 'React', 'FastAPI')
try:
frozen[0] = "Django"
except TypeError as error:
print("TypeError:", error)
# TypeError: 'tuple' object does not support item assignment
# The original list is untouched and still editable
courses.append("Flask")
print(courses)Loop over points = ((10, 20), (30, 40), (50, 60)) with tuple unpacking and print "Point: x=10, y=20" for each.
Show hintHide hint
Unpack in the for statement itself, not inside the body.
Show solutionHide solution
points = ((10, 20), (30, 40), (50, 60))
for x, y in points:
print(f"Point: x={x}, y={y}")
# Point: x=10, y=20
# Point: x=30, y=40
# Point: x=50, y=60Student records, read only
A fixed set of student results arrives as a tuple of tuples. Report on it using unpacking throughout, without converting the records to lists.
- Print each student name and score on its own line, using unpacking in the for statement.
- Find the highest score, and print the name of the student who got it.
- Print the course catalogue below in the format "PY101 - Core Python - Beginner".
- Prove the records cannot be modified by attempting one change and catching the error.
- Build a lookup dictionary keyed by a tuple of (course_id, level), and read one value back out of it.
students = (
("Ravi", 85),
("Anita", 92),
("Chandu", 88),
("Priya", 95),
)
courses = (
("PY101", "Core Python", "Beginner"),
("PY201", "Advanced Python", "Intermediate"),
("FA101", "FastAPI", "Intermediate"),
)
# 1. Name and score on each line
# 2. The highest score, and who got it
# 3. The catalogue lines
# 4. Prove it is immutable
# 5. A dictionary keyed by (course_id, level)
Show one solutionHide solution
students = (
("Ravi", 85),
("Anita", 92),
("Chandu", 88),
("Priya", 95),
)
courses = (
("PY101", "Core Python", "Beginner"),
("PY201", "Advanced Python", "Intermediate"),
("FA101", "FastAPI", "Intermediate"),
)
# 1. Unpack in the for statement - each record comes apart as it arrives
for name, score in students:
print(f"{name}: {score}")
# 2. max() with a key, then unpack the winning record.
# student[1] inside the key is the score.
top_name, top_score = max(students, key=lambda student: student[1])
print(f"Highest: {top_name} with {top_score}")
# Highest: Priya with 95
# 3. Three fields, three names
for course_id, title, level in courses:
print(f"{course_id} - {title} - {level}")
# PY101 - Core Python - Beginner
# PY201 - Advanced Python - Intermediate
# FA101 - FastAPI - Intermediate
# 4. The tuple will not rebind an element
try:
students[0] = ("Ravi", 100)
except TypeError as error:
print("TypeError:", error)
# TypeError: 'tuple' object does not support item assignment
# 5. A composite key - immutable, so the dictionary can rely on it
by_id_and_level = {}
for course_id, title, level in courses:
by_id_and_level[(course_id, level)] = title
print(by_id_and_level[("FA101", "Intermediate")]) # FastAPI
# A list key would have been refused here:
# by_id_and_level[[course_id, level]] = title
# TypeError: unhashable type: 'list'Key points
- The comma creates a tuple, not the parentheses - (10) is an int and (10,) is a tuple.
- The empty tuple () is the one case that needs no comma.
- Indexing, slicing, +, *, in, and comparison all work exactly as they do on lists, and slices return tuples.
- A tuple has only two methods: count() and index(). Nothing that would change it exists.
- Immutability is one level deep - a tuple holding a list still lets that list change.
- Unpacking assigns elements to names in one line, and the counts must match or you get ValueError.
- A starred name collects the rest and is always a list, possibly empty.
- a, b = b, a swaps without a temporary, because the right side is packed before anything is assigned.
- Returning several values is just packing and unpacking - the result really is a tuple.
- A tuple of hashable values can be a dictionary key; a list can never be one.
- Choose a tuple for a fixed record, a list for a collection that changes.
Quick check before you move on
Interview questions
What is a tuple?
An ordered, immutable sequence. It supports indexing, slicing, iteration, and membership like a list, but once created its elements cannot be replaced, added to, or removed.
What is the difference between a list and a tuple?
Mutability, and everything follows from it. A list can be changed and so has append, remove, and sort; a tuple cannot and so has only count and index. A tuple can be a dictionary key when its contents are hashable; a list never can.
How do you create a single-element tuple, and why is that the syntax?
With a trailing comma: (10,). Parentheses only group in Python - the comma is the tuple constructor. (10) is just the integer inside redundant brackets.
Can a tuple contain mutable objects, and what does that mean for immutability?
Yes. The tuple fixes which objects it references, not their contents. ([1, 2], [3, 4]) will not let you rebind an element but will let you append to the inner list, so a tuple is only truly frozen when its elements are immutable too.
What is extended unpacking?
Using a starred name to absorb an arbitrary number of elements: first, *middle, last = values. The starred name becomes a list, there can be at most one per assignment, and it may collect nothing.
What actually happens when a function returns multiple values?
Nothing special. return a, b packs the values into a tuple and returns that one object; the caller unpacks it. type() on the result confirms it is a tuple.
Why can a tuple be a dictionary key when a list cannot?
A key must hash consistently for as long as it is stored. Lists are mutable, so their hash could change after insertion and the dictionary could no longer locate the entry - Python makes them unhashable rather than allow that. A tuple of hashable values cannot change, so it is safe.
How does a, b = b, a work without a temporary variable?
The right-hand side is evaluated first and packed into a tuple from the current values, then that tuple is unpacked into the left-hand names. Both original values are already captured before any assignment happens.
Is a tuple faster or smaller than a list?
Slightly smaller, and constructing a constant one is faster because CPython can build it at compile time. The difference rarely matters - choose based on whether the data should be able to change, not on micro-performance.
When would you use a tuple over a list in real code?
For a fixed record such as a coordinate or a database row, for returning several values, for a constant sequence such as allowed roles, and for a composite dictionary key. Anywhere the collection grows or shrinks, use a list.
What are the limits of using tuples as records?
Fields are positional, so past three or four values the meaning becomes hard to read and a swapped order is a silent bug rather than an error. At that point a NamedTuple, dataclass, or dictionary gives the fields names.
Where do tuples show up without you creating them?
enumerate() yields (index, value) pairs, zip() yields one tuple per position, database drivers return rows as tuples, and multiple return values are tuples. Most tuple unpacking people write is against tuples they never constructed.
Quiz
- 1.
How do you add an element to a tuple?
- 2.
Which methods does a tuple have?
- 3.
What type is the starred variable in first, *rest = data?
- 4.
Does slicing a tuple give you a list?
- 5.
When is a tuple not hashable?
Comments
Sign in to leave a comment. Your name and photo come from Google; nothing else is shared.
Loading comments...
AI
System Design
Backend
- GraphQL8 modules · 69 lessons planned
- Core Python13 modules · 75 lessons planned
- FastAPI5 sections · 20 lessons
- Node.js14 modules · 206 lessons planned
- Node.js Performance7 chapters · 36 topics
- Event Loop Lifecycle6 phases · 3 scenarios
- Docker & Containerization11 modules · 144 lessons planned
- AWS for Developers14 modules · 219 lessons planned
- CI/CD & DevOps Automation10 modules · 134 lessons planned