The Walrus Operator
Reviewed & published by Brayan K
The walrus operator := is an assignment expression that assigns a value to a variable and returns that value at the same time, letting you capture a result inside a larger expression.
Part of the free Python course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
Added in Python 3.8, it trims duplication in while loops, if conditions, and comprehensions — computing a value once and reusing it on the very same line.
What You'll Learn in This Lesson
- What an assignment expression is
- How := differs from a plain =
- Reading input cleanly in while loops
- Reusing a computed value in an if condition
- Capturing values inside comprehensions
- Knowing when := helps vs hurts readability
1 Assign and Use in One Step
A plain = is a statement and produces no value. The walrus := is an expression: it assigns and hands back the value, so it can live inside a bigger expression:
# Without the walrus: compute, then test
data = [1, 2, 3, 4, 5]
n = len(data)
if n > 3:
print(f"List is long ({n} items)") # List is long (5 items)
# With the walrus: capture n right in the condition
if (n := len(data)) > 3:
print(f"List is long ({n} items)") # List is long (5 items)
# The walrus returns the value it just assigned
print((x := 10)) # 10 -> x is now 10
print(x + 5) # 15🔁 Cleaner while Loops
The walrus removes the awkward "read once before the loop, then read again at the bottom" pattern. Read and test in the condition itself:
# Simulate reading lines until a blank one
lines = iter(["alpha", "beta", "", "gamma"])
# The clunky pattern: duplicate the read
# line = next(lines)
# while line != "":
# print(line)
# line = next(lines) # <- repeated!
# With the walrus: one read, no duplication
while (line := next(lines)) != "":
print("Got:", line)
print("Stopped at blank line")
# Expected:
# Got: alpha
# Got: beta
# Stopped at blank lineEach loop iteration calls next(lines), stores the result in line, and tests it — all in one place. No more forgetting to repeat the read at the bottom of the loop.
# Process chunks until an empty one appears
chunks = iter(["data1", "data2", "data3", "", "ignored"])
total = 0
while (chunk := next(chunks)) != "":
total += len(chunk)
print("Processing:", chunk)
print("Total chars:", total)
# ✅ Expected output:
# Processing: data1
# Processing: data2
# Processing: data3
# Total chars: 152 Reuse a Value in Comprehensions & Conditions
When an expensive or repeated computation appears in a comprehension's filter and its output, the walrus computes it once:
def process(n):
return n * n - 1 # pretend this is expensive
nums = [1, 2, 3, 4, 5]
# Without walrus: process(n) runs TWICE per item
result = [process(n) for n in nums if process(n) > 5]
# With walrus: compute once, reuse the result
result = [y for n in nums if (y := process(n)) > 5]
print(result) # [8, 15, 24]
# Walrus in an if, reusing the match
import re
text = "order: 42"
if (m := re.search(r"\d+", text)):
print("Found number:", m.group()) # Found number: 42# Capture a value once, reuse it in the same comprehension
words = ["hi", "hello", "hey", "greetings", "yo"]
# Keep words longer than 3 chars, and report their length
result = [(w, n) for w in words if (n := len(w)) > 3]
print(result) # [('hello', 5), ('greetings', 9)]
# Walrus inside an if, reusing the computed total
basket = [4, 9, 2, 7]
if (total := sum(basket)) > 20:
print(f"Over budget by {total - 20}") # Over budget by 2
else:
print(f"Under budget: {total}")
# ✅ Expected output:
# [('hello', 5), ('greetings', 9)]
# Over budget by 2⚖️ Readability Limits
The walrus is a scalpel, not a hammer. It helps when it removes duplication; it hurts when it crams unrelated work into one line:
# 👍 GOOD: removes a real duplicate computation
if (size := len(payload)) > 1024:
print(f"Too big: {size} bytes")
# 👎 BAD: hard to read, no real benefit
print(y := (x := 5) + (z := 3)) # too clever, avoid
# 👍 Often clearer as two plain lines:
x = 5
z = 3
y = x + z
print(y)Ask: "does := remove duplication or save a meaningful line?" If yes, use it. If it just looks clever, prefer two ordinary lines — clarity wins.
🎯 Your Turn: Fill in the Blanks
Replace each ___ with a walrus assignment so the output matches.
# 🎯 YOUR TURN: replace each ___ with a walrus (name := value)
data = [3, 8, 1, 9, 4]
# 1. Capture the max in the condition and reuse it
if (___) > 8: # hint: biggest := max(data)
print(f"Peak is {biggest}") # Peak is 9
# 2. In a comprehension, square each item once and keep squares > 10
squares = [s for n in data if (___) > 10] # hint: s := n * n
print(squares) # [64, 81, 16]
# Expected output:
# Peak is 9
# [64, 81, 16]if (biggest := max(data)) > 8:
print(f"Peak is {biggest}")
squares = [s for n in data if (s := n * n) > 10]
print(squares) # [64, 81, 16]Common Errors & How to Fix Them
❌ Using a plain = in a condition
if (n = len(data)) > 3: # SyntaxError - = is not an expression✅ Use the walrus inside conditions: if (n := len(data)) > 3:. Plain = only works as its own statement.
total = sum(x := 5, ...) # ambiguous / SyntaxError in many spots✅ Wrap the walrus: (x := 5). The parentheses resolve precedence and make the assignment clear.
❌ Reaching for it on Python 3.7 or older
# SyntaxError on Python < 3.8✅ The walrus needs Python 3.8+. On older versions, assign on a separate line first.
🎯 Mini Challenge: Running Threshold
Use the walrus to find the first running total that crosses a threshold.
# Mini Challenge: stop when the running total exceeds 15
amounts = [4, 3, 6, 5, 8]
running = 0
for a in amounts:
if (running := running + a) > 15:
print(f"Crossed 15 at +{a}, total={running}")
break
print(f"Added {a}, total={running}")
# Bonus: keep only readings whose doubled value exceeds 10, once
readings = [3, 7, 2, 9]
big = [d for r in readings if (d := r * 2) > 10]
print("Doubled & big:", big)
# Expected output:
# Added 4, total=4
# Added 3, total=7
# Added 6, total=13
# Crossed 15 at +5, total=18
# Doubled & big: [14, 18]📚 Keep Learning
Go deeper with the official Python documentation:
- PEP 572 — Assignment Expressions — the proposal that introduced the walrus, with motivation and examples.
- Language Reference — Assignment Expressions — the formal grammar and scoping rules for :=.
- What's New in Python 3.8 — the release notes that first shipped the operator.
Frequently Asked Questions
Lesson complete — the walrus is tamed!
You can assign and use a value in one expression with :=, write cleaner while loops, reuse computations in comprehensions and conditions, and judge when it helps versus when it just looks clever.
Practice quiz
What does the walrus operator := do?
- It compares two values for equality
- It only works inside function definitions
- It assigns a value to a variable AND returns that value as an expression
- It deletes a variable after use
Answer: It assigns a value to a variable AND returns that value as an expression. The walrus := is an assignment expression: it assigns and evaluates to the assigned value, so it can live inside conditions and comprehensions.
In which Python version was the walrus operator introduced?
- Python 3.8
- Python 3.6
- Python 3.7
- Python 3.10
Answer: Python 3.8. PEP 572 added the walrus operator in Python 3.8; using it on 3.7 or older raises a SyntaxError.
Why does a plain = fail inside an if condition like 'if (n = len(data)) > 3:'?
- Because = is too slow there
- Because len() cannot be used in conditions
- Because n is a reserved word
- Because plain = is a statement, not an expression, so it produces no value to test
Answer: Because plain = is a statement, not an expression, so it produces no value to test. Plain = is a statement and yields no value, so it is a SyntaxError inside a condition. The walrus := is an expression and works.
What is the value of x after this runs: print((x := 10))?
- None
- 10
- True
- It raises an error
Answer: 10. (x := 10) assigns 10 to x and returns 10, so 10 is printed and x is now 10.
What does this print? squares = [s for n in [1,2,3] if (s := n*n) > 3]; print(squares)
- [4, 9]
- [1, 4, 9]
- [2, 3]
- [9]
Answer: [4, 9]. n*n is computed once per item and bound to s; only squares > 3 are kept, giving [4, 9] (4 from 2, 9 from 3).
A key benefit of the walrus inside a while condition is that it:
- Makes the loop run faster than any other form
- Automatically stops infinite loops
- Lets you read and test a value in one place, removing a duplicated read
- Converts the loop into a comprehension
Answer: Lets you read and test a value in one place, removing a duplicated read. while (line := next(lines)) != '': reads and tests in the condition, eliminating the clunky 'read before, read again at the bottom' duplication.
Why is wrapping the walrus in parentheses, like (n := len(data)), recommended?
- Parentheses make it run at compile time
- It resolves precedence and is always syntactically safe and clear
- Python deletes the variable without them
- It is required to import the operator
Answer: It resolves precedence and is always syntactically safe and clear. Parentheses make precedence explicit and keep the assignment valid and obvious; bare := is sometimes rejected or read oddly.
In a comprehension, what is the walrus's main advantage when a function appears in both the filter and the output?
- It sorts the result automatically
- It makes the comprehension lazy
- It removes the need for a for clause
- It computes the function once per item instead of twice
Answer: It computes the function once per item instead of twice. [y for n in nums if (y := f(n)) > 5] calls f(n) once per item and reuses y, instead of calling f(n) in both the filter and the output.
When is the walrus operator a POOR choice?
- When it removes a genuine duplicated computation
- When it crams unrelated assignments into one line just to look clever
- When used in a while condition
- When wrapped in parentheses
Answer: When it crams unrelated assignments into one line just to look clever. The walrus shines at removing real duplication; using it to golf unrelated work into one dense line hurts readability.
After 'if (biggest := max([3,8,1,9,4])) > 8:', what value does biggest hold inside the block?
- 8
- True
- 9
- 4
Answer: 9. max([3,8,1,9,4]) is 9, which is assigned to biggest and is greater than 8, so the block runs with biggest == 9.
Continue this course
- Previous: Conditional Expressions (Ternary)
- Next: Structural Pattern Matching (match/case) — Match literals, sequences, mappings and classes with guards (3.10+)
- Quick reference: Python cheat sheet
Frequently asked questions
What is the walrus operator?
The walrus operator := is an assignment expression, added in Python 3.8. It assigns a value to a variable AND returns that value at the same time, so you can capture a result right inside a larger expression — like an if, while, or comprehension — instead of needing a separate assignment line first.
Why is it called the walrus operator?
Because := looks like the eyes and tusks of a walrus tilted on its side. The official name is 'assignment expression', but the nickname stuck. It was introduced by PEP 572 and is one of the few operators with a memorable face.
How is := different from =?
Plain = is a statement: it assigns but produces no value, so you can't put it inside an if or while condition. The walrus := is an expression: it assigns AND evaluates to the assigned value, so it can live inside conditions, comprehensions, and function arguments where a bare = is a syntax error.
When should I avoid the walrus operator?
Avoid it when it hurts readability. Cramming an assignment into an already-complex line, or using it just to save one short line, makes code harder to scan. It shines when it removes genuine duplication — computing a value once and reusing it in the same condition — not as a golfing tool to shorten everything.