← Python Code Loops, Functions & Scopes
Browse Python Concepts

The Walrus Operator := and Assignment Expressions

Mental Model

Think of := as a new kid on the block whose handshake is weaker than established operators like is not. Without explicit instructions (parentheses), the older, stronger operators will grab their operands first, leaving := to operate on whatever results remain.

Rule: When combining the walrus operator := with comparison operators, always wrap the assignment expression in explicit parentheses to override operator precedence.

The Setup

You are parsing chunked network streams. You want to extract length-prefixed data packets and validate them in a single condition to keep the control loop compact.

What Does This Print?

Broken code
Python
# Simulated network stream payload
stream = [b"data-chunk-1", b"data-chunk-2", b""]

def get_next_chunk():
    return stream.pop(0) if stream else None

# Attempting to assign chunk and check if it is valid in a comparison
while chunk := get_next_chunk() is not None:
    # We expect chunk to hold the actual bytes
    print(f"Processing chunk of length: {len(chunk)}")
Predict what happens when you run this code. Will it print the chunk lengths or raise an error?

The Output

What actually happens
TypeError: object of type 'bool' has no len()

The code raises a TypeError because the variable chunk gets bound to the boolean value True instead of the raw bytes payload. This occurs because the assignment operator := has a lower operator precedence than the comparison operator is not.

Why Python Does This

According to Python's operator precedence rules, comparison operators (such as is not, ==, <, etc.) bind tighter than the assignment expression operator :=. Therefore, the expression get_next_chunk() is not None evaluates first, returning a boolean value (True or False). This boolean result is then assigned to the variable chunk via the walrus operator. Additionally, variables bound by := do not respect block boundaries like list comprehensions; they spill over into the enclosing function scope.

The Fix

Corrected pattern
Python
stream = [b"data-chunk-1", b"data-chunk-2", b""]

def get_next_chunk():
    return stream.pop(0) if stream else None

# Wrap the assignment in parentheses to force it to execute first
while (chunk := get_next_chunk()) is not None:
    print(f"Processing chunk of length: {len(chunk)}")

Wrapping the assignment expression (chunk := get_next_chunk()) in parentheses explicitly defines its evaluation order. This forces get_next_chunk() to execute and its result to be assigned to chunk before the is not None comparison is performed, ensuring chunk holds the actual data.

How This Fails in Real Systems

A developer used a walrus operator inside a high-frequency socket reader loop to read and validate data envelopes. Lacking parentheses, the boolean binding resulted in the system attempting to slice operations on a Boolean, crashing the ingestion server and causing a 4-hour backend telemetry outage.

Key Takeaway

When combining the walrus operator := with comparison operators, always wrap the assignment expression in explicit parentheses to override operator precedence.
Common mistake: Developers overlook the operator precedence of := relative to comparison operators, leading to := assigning the result of the entire comparison expression rather than just the intended value.