Python Multiple Assignment: Syntax and Behavior
python multiple assignment: Learn how Python multiple assignment evaluates the right side first, swaps variables, unpacks iterables, and where it breaks down.
python multiple assignment requires a clear understanding of the core syntax, runtime behavior, and practical implementation patterns demonstrated in the examples below.
Python's multiple assignment lets you assign several variables in a single statement, but the way it evaluates the right side determines what works and what silently fails.
How Multiple Assignment Evaluates the Right Side First
When you write:
a, b = 1, 2
Python builds a tuple (1, 2) on the right and unpacks it into a and b. The right-hand side is fully evaluated before any assignment happens. That ordering matters for expressions that depend on the current values of the variables being assigned.
x = 1 y = 2 x, y = y, x
The right side y, x is evaluated first, producing (2, 1). Only then are the assignments performed. This is why the swap works without a temporary variable. If assignments happened left-to-right as they were written, x would be overwritten before y received its new value.
This evaluation order also applies when the right side contains function calls or expressions:
a, b = compute_a(), compute_b()
Both functions run before either variable is assigned. If compute_b depended on the new value of a, that dependency would not be visible inside the expression.
Swapping Variables Without a Temporary
The swap idiom is the most common use of multiple assignment in everyday code.
left = "first" right = "second" left, right = right, left
After this, left holds "second" and right holds "first". The temporary tuple on the right side holds both original values until the unpacking completes, so no data is lost.
This is more readable than the equivalent three-line version with an explicit temporary:
temp = left left = right right = temp
The multiple-assignment version communicates the intent directly and removes a variable that exists only to hold a value during the swap.
Unpacking Sequences and Iterables
Multiple assignment is not limited to tuples. Any iterable of the matching length can be unpacked:
first, second = ["alpha", "beta"] x, y = (10, 20) key, value = {"name": "Ada"}.popitem()
The unpacking works on lists, tuples, strings, and any object that implements the iterator protocol. When the number of elements does not match the number of targets, Python raises a ValueError:
a, b = [1, 2, 3] # ValueError: too many values to unpack a, b, c = [1, 2] # ValueError: not enough values to unpack
This strictness is usually desirable because it surfaces mismatches early rather than silently dropping or padding data. When you intentionally want to ignore part of a sequence, the underscore convention is common:
first, _, last = [1, 2, 3]
The underscore is a regular variable name in Python, but by convention it signals that the value is not used.
Extended Unpacking With Star Expressions
Python 3 added extended unpacking, which lets one target collect the remaining elements:
head, *tail = [1, 2, 3, 4] # head = 1, tail = [2, 3, 4] *init, last = [1, 2, 3, 4] # init = [1, 2, 3], last = 4 first, *middle, last = [1, 2, 3, 4, 5] # first = 1, middle = [2, 3, 4], last = 5
The star target always collects a list, even when there is exactly one remaining element. Only one star expression is allowed per assignment statement:
a, *b, *c = [1, 2, 3] # SyntaxError
This pattern is useful when processing the first element of a sequence separately from the rest, such as parsing a command name and its arguments:
command, *args = user_input.split()
Where Multiple Assignment Breaks Down
The most common failure is a length mismatch, which raises ValueError. A subtler issue appears when the right side is a generator or an iterator that is consumed lazily.
def generate(): yield 1 yield 2 yield 3 a, b = generate() # ValueError: too many values to unpack
The generator is fully consumed during unpacking, and if it produces more values than the targets, the error is raised after the generator has been exhausted. This matters when the generator has side effects: those side effects have already run by the time the error appears.
Another limitation is that multiple assignment does not work directly on slices or attributes in all cases. Assigning to a slice requires a slice object:
items = [1, 2, 3, 4] items[0], items[1] = items[1], items[0] # works, swaps elements
This works because each target is an assignable expression, but the evaluation order still applies. Both right-side values are read before either element is written.
Runtime Cost and Readability Tradeoffs
Multiple assignment creates a tuple on the right side in the bytecode, but the overhead is negligible in normal code. The more important consideration is readability and maintainability.
When the number of targets grows beyond three or four, the statement becomes harder to read:
a, b, c, d, e = get_five_values()
At that point, a named structure such as a dataclass or a NamedTuple communicates the meaning of each field better than positional unpacking. The reader no longer has to count positions to know what c represents.
Multiple assignment is most valuable when the structure is small, the order is meaningful, and the variable names make the intent clear:
status, message = api_response() latency_ms, error = measure_request(url)
When the number of values is large or the meaning is not obvious from position, prefer a named container. The unpacking syntax remains useful, but the data structure should carry the semantics.