DevHireLab
Tutorials
BootcampProblemsCode SimulatorAI InterviewSoonContact
DevHireLab
Tutorials
BootcampProblemsCode SimulatorAI InterviewSoonContact
Getting Started
01
What is Python and Why Learn It in 2026
02
Installing Python on Windows, Mac, and Linux
03
Setting up VS Code / PyCharm for Python
04
Understanding the Python Interpreter and REPL
05
Writing and Running Your First Python Program
06
Python Syntax and Indentation Rules
Variables and Data Types
01
Variables and Naming Conventions in Python
02
Numbers in Python (int, float, complex)
03
Strings and String Methods in Python
04
Booleans in Python
05
Type Conversion / Casting in Python
06
Understanding the None Type in Python
Operators
01
Arithmetic Operators in Python
02
Comparison Operators in Python
03
Logical Operators in Python
04
Assignment Operators in Python
05
Bitwise Operators in Python
06
Identity (is) and Membership (in) Operators
07
Walrus Operator (:=) in Python
Input, Output & Strings
01
input() and print() Functions in Python
02
f-strings and String Formatting in Python
03
String Slicing and Indexing in Python
04
Common String Methods (split, join, strip, replace)
05
Escape Characters in Python Strings
Control Flow
01
if, elif, else Statements in Python
02
Nested Conditionals in Python
03
for Loops in Python
04
while Loops in Python
05
break, continue, and pass Statements
06
Loop with else Clause in Python
07
match-case (Structural Pattern Matching)
Data Structures
01
Python Lists: Creation, Indexing, Slicing, Methods
02
Python Tuples and Immutability
03
Python Sets and Set Operations
04
Python Dictionaries: Keys, Values, and Methods
05
List Comprehensions in Python
06
Dictionary & Set Comprehensions in Python
07
Working with Nested Lists and Dictionaries
Functions
01
Defining and Calling Functions in Python
02
Function Arguments: Positional, Keyword, Default
03
*args and **kwargs in Python
04
Return Statements in Python Functions
05
Lambda Functions in Python
06
Recursion in Python
07
Variable Scope: Local, Global, Nonlocal
08
Docstrings and Function Annotations
Functional Programming Basics
01
map(), filter(), and reduce() in Python
02
Closures in Python Explained
03
Python Decorators: Basic to Advanced
04
Generators and yield in Python
Object-Oriented Programming (OOP)
01
Classes and Objects in Python
02
The init Constructor in Python
03
Instance vs Class Variables in Python
04
Inheritance in Python (Single, Multiple, Multilevel)
05
Polymorphism in Python
06
Encapsulation in Python
07
Abstraction in Python with the abc Module
08
Magic/Dunder Methods in Python
09
Static and Class Methods in Python
10
The @property Decorator in Python
11
Python Dataclasses Explained
Error Handling
01
try, except, finally in Python
02
Handling Multiple Exceptions in Python
03
Raising Custom Exceptions in Python
04
Understanding Python's Exception Hierarchy
05
Assertions in Python
File Handling
01
Reading and Writing Text Files in Python
02
Working with the with Statement in Python
03
Working with CSV Files in Python
04
Working with JSON Files in Python
05
Working with Directories (os, pathlib) in Python
Modules and Packages
01
Importing Built-in Modules in Python
02
Creating Your Own Modules in Python
03
Understanding Packages and init.py
04
Python Standard Library Overview
05
Installing Packages with pip
Advanced Core Concepts
01
Iterators and Iterables in Python
02
Context Managers in Python (with, contextlib)
03
Multithreading Basics in Python
04
Multiprocessing Basics in Python
05
Asyncio Basics: async/await in Python
06
Memory Management and Garbage Collection in Python
07
Type Hints in Python (typing module)

Walrus Operator (:=) in Python

The python walrus operator is one of the more debated additions to modern Python — genuinely useful in the right spots, genuinely overused in the wrong ones. This article covers what it actually does, where it earns its place, and the scoping quirks that have tripped up even experienced developers.

What Is the Walrus Operator?

The walrus operator, written :=, was introduced in Python 3.8 through PEP 572. Officially, it's called an assignment expression — and that name is the whole point. A regular = assignment in Python is a statement; it doesn't produce a value you can use anywhere else. := is different: it assigns a value to a variable and returns that value, all within a single expression.

The "walrus" nickname comes from the symbol's shape — := is said to resemble a walrus's eyes and tusks turned sideways. It's an informal name, but it's the one that stuck, and you'll see walrus operator used interchangeably with "assignment expression" throughout Python discussions.

The core idea
# Regular assignment — a statement, can't be used inside another expression
n = 10

# Assignment expression — assigns AND returns the value, usable inline
if (n := 10) > 5:
    print(n)

That distinction — statement versus expression — is what unlocks everything else in this article.

Basic Syntax and How It Differs from =

The classic motivating example
data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]

# Traditional two-line version
n = len(data)
if n > 10:
    print(f"Data has {n} items")
# Same logic, using the walrus operator
if (n := len(data)) > 10:
    print(f"Data has {n} items")

Both do exactly the same thing. The walrus version avoids declaring n on its own separate line, while still giving you a name you can reuse inside the if block.

Why plain = can't do this

Python deliberately keeps = as a statement, not an expression — this is intentional language design, not an oversight. It's why something like if n = len(data): has always been a syntax error in Python, even though the equivalent is legal in languages like C or JavaScript. The walrus operator exists specifically to provide a safe, explicit way to do this kind of inline assignment, without reopening the door to the classic =-versus-== typo bug that plain assignment-as-expression invites in those other languages.

Parentheses are usually required

In most contexts, := needs to be wrapped in parentheses:

if (n := len(data)) > 10:
    print(n)
Precedence matters

This is the detail most likely to catch you off guard: := binds lower than most operators, including comparison operators. That means writing it without parentheses can silently produce something very different from what you intended:

if n := 5 > 4:
    print(n)

This doesn't assign 5 to n and then check if it's greater than 4. Because := has lower precedence than >, Python evaluates 5 > 4 first (giving True), and that's what gets assigned to n. The output is True, not 5 — probably not what you expected from reading the line. Always wrap the walrus assignment itself in parentheses around exactly the value you mean to capture: (n := 5) > 4.

Practical Use Cases

Avoiding repeated or expensive function calls

The most common motivation for using := is avoiding calling the same function twice — once to compute a value, and again inside a condition or comprehension that uses it:

# Without walrus — complex_calculation() runs, and the result needs a separate line
results = []
for x in data:
    value = complex_calculation(x)
    if value > threshold:
        results.append(value)
# With walrus, inside a list comprehension
results = [value for x in data if (value := complex_calculation(x)) > threshold]

The second version computes complex_calculation(x) exactly once per item, reusing it for both the filter condition and the final collected value — instead of calling it twice or restructuring the whole thing into a full loop.

while loops reading until a sentinel

This is arguably the walrus operator's best-fit use case: reading from a file, socket, or user input until you hit some ending condition.

# Reading a file line by line until it's exhausted
with open("data.txt") as file:
    while (line := file.readline()):
        print(line.strip())

Without the walrus operator, this pattern traditionally required either a slightly awkward while True: loop with a manual break, or reading the first line before the loop and again at the end of each iteration — both noticeably more repetitive than the version above.

Regex matching in one line

Regular expression matching often involves capturing a match object and immediately checking whether it succeeded — a natural fit for :=:

import re

pattern = re.compile(r"\d+")
text = "There are 42 apples"

if match := pattern.search(text):
    print(f"Found: {match.group()}")

This avoids a separate match = pattern.search(text) line before the if, without losing access to the match object inside the block.

Common Pitfalls and Gotchas

Variable scope

Here's a subtlety worth understanding well: a variable assigned with := inside a comprehension binds to the enclosing scope, not to the comprehension's own internal scope, by design. This is different from the comprehension's own loop variable, which stays contained.

def check_values(data, threshold):
    results = [y for x in data if (y := x * 2) > threshold]
    print(y)   # this works — y leaked out of the comprehension into the function scope
    return results

This is intentional behavior per PEP 572, not a bug — but it did have a rough edge in early releases: in Python 3.8 and 3.9, this leaking behavior could behave inconsistently in certain scopes, such as at class-body or module level. That inconsistency was cleaned up by Python 3.10, and the behavior has been stable and well-defined since. If you're working in a codebase that still needs to support 3.8 or 3.9, it's worth testing this specific pattern carefully rather than assuming it behaves identically everywhere.

Where it's disallowed entirely

A few contexts don't permit := at all:

  • Plain top-level assignment — you can't write n := 5 as a standalone statement in place of n = 5. The walrus form must appear as part of a larger expression.

  • Inside a lambda function's body — walrus assignment isn't permitted there.

  • As the context manager expression in a with statement — with (f := open("file.txt")): would bind f to the file object itself returned by the expression, not to what __enter__() returns, which is usually not what you actually want from a with statement. This is a subtle enough trap that it's worth avoiding the pattern entirely rather than trying to reason through it each time.

The readability risk

Because := lets you cram an assignment into what used to be a simple condition or comprehension, it's easy to overuse. Multiple walrus operators nested in a single dense expression, or a walrus assignment buried inside an already-complicated comprehension, can genuinely make code harder to follow rather than easier — the opposite of the readability goal PEP 572 was designed around.

Best Practices: When to Use It (and When Not To)

Good fits
  • while loops that read incrementally — files, sockets, streamed input — until some ending condition.

  • Guard clauses where you need both the result and a check on it: if (result := risky_call()) is not None:.

  • Comprehensions with an expensive filter computation that would otherwise need to run twice.

When to skip it

If a plain, two-line traditional assignment is just as clear, use that instead. The walrus operator wasn't designed to compress every possible assignment into an expression — it exists specifically to eliminate genuine redundancy, like a duplicated function call. If there's no redundancy to eliminate, reaching for := mostly just adds unfamiliar syntax without a real benefit.

Guidance for team codebases

If you're working with other developers, treat := as a tool for clarity, not an opportunity to show off compact syntax. A good rule of thumb: if you have to pause and mentally unpack what a line is doing before you can explain it to someone else, it's probably not the right spot for a walrus operator — even if it technically works.

PREVIOUSNEXT LESSON