Python walrus operator
last modified May 10, 2026
In this article we show how to use the walrus operator in Python.
Python 3.8 introduced the walrus operator, written as :=.
The name comes from the fact that the symbol resembles the eyes and tusks
of a walrus seen from the side. Formally, the feature is called an
assignment expression because it allows you to assign a value
to a variable *inside* a larger expression.
The walrus operator makes code more compact by combining an assignment with a condition, a return value, or a comprehension. Instead of writing the assignment on a separate line and then testing the variable, you can do both in one step. However, it should be used judiciously – clarity should never be sacrificed for brevity.
print(is_new := True)
Here we assign True to the variable is_new and
immediately pass that value to print(). The expression
(is_new := True) evaluates to True, so the output
is True.
is_new = True print(is_new)
Without the walrus operator, we need two lines: one for the assignment and one for the print. The walrus version collapses them into a single expression.
Reading input
In the following example, we use the walrus operator inside a
while loop to read user input until the user types “quit”.
#!/usr/bin/python
words = []
while (word := input("Enter word: ")) != "quit":
words.append(word)
print(words)
The expression (word := input("Enter word: ")) does two things:
it prompts the user for input and assigns the result to word.
The whole expression then returns that value, which is compared against
"quit". Without the walrus operator you would need to call
input() separately inside the loop body, duplicating the prompt
or writing an endless loop with a break.
$ ./read_words.py Enter word: cloud Enter word: falcon Enter word: rock Enter word: quit ['cloud', 'falcon', 'rock']
Walrus with if condition
Suppose that all our words must have at least three characters. The walrus
operator can capture the length of a word and test it in one
if-statement.
#!/usr/bin/python
words = ['falcon', 'sky', 'ab', 'water', 'a', 'forest']
for word in words:
if ((n := len(word)) < 3):
print(f'warning, the word {word} has {n} characters')
Inside the condition if ((n := len(word)) < 3), the variable
n is assigned the length of the current word, and that length is
then compared to 3. If the condition is true, we already have n
available to use in the warning message. Without the walrus, we would need to
call len(word) twice or introduce a separate assignment line.
$ ./test_length.py warning, the word ab has 2 characters warning, the word a has 1 characters
Reading a file
The walrus operator is especially handy when reading a file line by line.
falcon sky cloud water rock forest
#!/usr/bin/python
with open('words.txt', 'r') as f:
while line := f.readline():
print(line.rstrip())
The readline() method returns an empty string when the end of
the file is reached. The expression line := f.readline()
assigns each line to line and then the while loop
evaluates it; a non-empty string is truthy, an empty string is falsy, so
the loop stops automatically. This eliminates the need for a separate
line = f.readline() before the loop and at the end of each
iteration.
Traversing a container
When working with lists of dictionaries that may contain missing values, the walrus operator helps to extract and test data in one go.
#!/usr/bin/python
users = [
{'name': 'John Doe', 'occupation': 'gardener'},
{'name': None, 'occupation': 'teacher'},
{'name': 'Robert Brown', 'occupation': 'driver'},
{'name': None, 'occupation': 'driver'},
{'name': 'Marta Newt', 'occupation': 'journalist'}
]
for user in users:
if ((name := user.get('name')) is not None):
print(f'{name} is a {user.get("occupation")}')
The expression name := user.get('name') retrieves the value for
the key 'name' (which may be None) and binds it to
name. The is not None check then decides whether to
print the user. The alternative would require a separate line to fetch the
name before the if.
$ ./traversing.py John Doe is a gardener Robert Brown is a driver Marta Newt is a journalist
Only users with a non-None name are shown.
Regular expressions
Regular expression searches are another natural fit. The walrus operator allows you to perform a match and check its success at the same time.
#!/usr/bin/python
import re
data = 'There is a book on the table.'
pattern = re.compile(r'book')
if match := pattern.search(data):
print(f'The word {pattern.pattern} is at {match.start(), match.end()}')
else:
print(f'No {pattern.pattern} found')
match := pattern.search(data) runs the search and assigns the
result (a match object or None). Because assignment expressions
evaluate to the assigned value, the if block executes only when
a match is found, and we already have the match object ready for further
inspection.
$ ./search.py The word book is at (11, 15)
The word book was found at indices 11 to 15.
List comprehensions
One of the most powerful uses of the walrus operator is inside list comprehensions. It lets you reuse a computed value without calling the function twice.
#!/usr/bin/python
def normalize(s):
return s.strip().title()
raw_names = [' john ', 'JANE', ' bob ', 'ALICE']
# Without walrus - normalization called twice
names1 = [normalize(n) for n in raw_names if len(normalize(n)) > 3]
# With walrus - computed once and captured
names2 = [name for n in raw_names if (name := normalize(n)) and len(name) > 3]
print(names1)
print(names2)
In the first comprehension normalize(n) is called twice for
elements that pass the filter. In the second, the walrus operator captures
the result of normalize(n) in the variable name,
which is then immediately used in both the condition and the output expression.
This can improve performance when the computation is expensive.
Important: Variables assigned with the walrus operator inside
a comprehension leak into the surrounding scope (in Python 3.8+). After the
comprehension runs, name will still hold the last normalized
value. This is different from the iteration variable n, which
also leaks. Be mindful of unintentional side effects.
Function calls
The walrus operator can also be used to capture the return value of a
function call inside a while loop or an if
statement, avoiding a separate assignment beforehand.
#!/usr/bin/python
import random
def unreliable_operation():
# Simulates an operation that sometimes fails
return random.choice([None, 42, None, 42])
attempts = 0
while (result := unreliable_operation()) is None and attempts < 10:
attempts += 1
print(f'Attempt {attempts} failed, retrying...')
if result is not None:
print(f'Success after {attempts} attempts, result={result}')
else:
print('All attempts failed')
Here the loop condition both calls the function and binds its return value to
result. We then check if it is None and whether we
have retries left. After the loop, result is available for the
final decision. This pattern avoids declaring result before the
loop and updating it inside.
Socket communication
When writing network code, the walrus operator can simplify loops that read data in chunks until the connection is closed. In this example we connect to a web server and receive the response piece by piece.
import socket
import ssl
HOST = "example.com"
PORT = 443 # HTTPS default port
# Create a default SSL context (loads trusted CA certificates)
context = ssl.create_default_context()
# Build the request
request = (
f"GET / HTTP/1.1\r\n"
f"Host: {HOST}\r\n"
f"Connection: close\r\n"
f"\r\n"
).encode("utf-8")
# Establish the connection
with socket.create_connection((HOST, PORT)) as sock:
# Wrap the raw socket with SSL
# 'server_hostname' is required for the SSL handshake (SNI)
with context.wrap_socket(sock, server_hostname=HOST) as ssock:
ssock.sendall(request)
# Use the walrus operator to read the encrypted stream
while chunk := ssock.recv(4096):
print(chunk.decode("utf-8", errors="ignore"), end="")
The call to s.recv(4096) returns a bytes object of up to 4096
bytes. When the server closes the connection, recv() returns an
empty bytes object (b''), which is falsy. By using the walrus
operator in the loop condition, we capture each chunk in the variable
line and immediately evaluate it. The loop terminates
automatically once the empty chunk signals the end of the response.
Source
In this article we have worked with the Python walrus operator.
Author
List all Python tutorials.