Python 3.8: Walrus Operator := Controversy
Python 3.8 introduces the walrus operator (:=). It’s officially called “assignment expressions.” The debates were so heated that Guido van Rossum stepped down as BDFL.
Was it worth the drama?
What is the Walrus Operator?
It assigns a value to a variable as part of an expression:
# Before: Assign then use
data = get_data()
if data:
process(data)
# After: Assign within expression
if (data := get_data()):
process(data)
The variable data is assigned AND used in the same line.
Why “Walrus”?
:= looks like a walrus on its side. Eyes and tusks.
Practical Use Cases
While Loops
# Before
line = f.readline()
while line:
process(line)
line = f.readline()
# After
while (line := f.readline()):
process(line)
No more duplicated readline.
List Comprehensions with Side Effects
# Before: Call expensive function twice or use temporary list
results = []
for x in data:
y = expensive_computation(x)
if y > threshold:
results.append(y)
# After
results = [y for x in data if (y := expensive_computation(x)) > threshold]
Compute once, filter and use.
Regex Matching
# Before
match = pattern.match(line)
if match:
print(match.group(1))
# After
if (match := pattern.match(line)):
print(match.group(1))
Simplifying Conditionals
# Before
results = do_query()
if len(results) > 10:
print(f"Found {len(results)} results")
# After
if (n := len(results := do_query())) > 10:
print(f"Found {n} results")
Though this might be too clever.
The Controversy
Why People Objected
- Readability: Python values explicitness.
:=is subtle. - Abuse potential: Encourages clever one-liners
- Inconsistency: Different from regular assignment
- Debugging: Order of operations can be confusing
Why Guido Stepped Down
The PEP 572 debates were intense. Guido approved the PEP and faced significant pushback. He wrote:
“I’m tired, and need a break.”
He stepped down as BDFL (Benevolent Dictator For Life) after three decades.
Python now uses a Steering Council for governance.
Style Guidelines
Do Use When
Avoiding repeated expensive calls:
if (match := pattern.search(data)) is not None:
return match.group(0)
Reducing loop setup:
while (block := file.read(256)):
process(block)
Capturing intermediate values:
filtered = [y for x in data if (y := transform(x)) is not None]
Don’t Use When
It harms readability:
# Too clever
if (n := len(a := get_list())) > (m := len(b := get_other())):
...
The normal form is clearer:
# Just use this
data = get_data()
if data:
process(data)
In simple statements:
# Pointless
(x := 10) # Just write: x = 10
PEP 572 Restrictions
The walrus operator has limitations:
# Can't use at top level (use = instead)
(x := 10) # Requires parentheses
# Can't use in comprehension iteration target
[x := i for i in range(10)] # SyntaxError
# Can't use in f-string expressions without parentheses
f"{x:=10}" # This is formatting, not walrus
f"{(x := 10)}" # This works
Migration
Python 3.8+ only. Check:
import sys
if sys.version_info >= (3, 8):
# Can use walrus
Or just set minimum Python version in your project.
Other Python 3.8 Features
Don’t miss these:
Positional-Only Parameters
def greet(name, /, greeting="Hello"):
return f"{greeting}, {name}"
greet("Alice") # OK
greet(name="Alice") # TypeError
f-string = for debugging
x = 10
print(f"{x=}") # Output: x=10
typing.Final
from typing import Final
MAX_SIZE: Final = 100
Should You Use It?
Yes, sparingly.
The walrus operator is a tool. Like all tools, it can be misused. Good candidates:
- While loops with assignment
- Regex matches
- List comprehensions avoiding repeated calls
Bad candidates:
- Anywhere it reduces clarity
- Multiple walruses in one expression
- When the traditional form is just as clean
Final Thoughts
The walrus operator is a modest addition that caused immodest drama. It fills a real gap but isn’t revolutionary.
Use it where it genuinely simplifies code. Avoid it when you’re showing off. Python’s readability culture remains more important than any single operator.
Simple is better than complex. Unless you need a walrus.