Skip to main content
HomeTutorialsPython

Python's Walrus Operator: The Assignment Expression (Tutorial)

Python's walrus operator := allows you to assign a value to a variable within an expression, combining assignment and use in a single step.
Aug 2024  · 8 min read

Python 3.8 introduced a new operator to the language. Its official name is the assignment expression, and it uses the := operator.

However, it's more commonly called the walrus operator as it looks like the tasks of a walrus!

There was controversy in the normally calm Python world when this operator was added to the language, and its use is still relatively limited. Still, the assignment expression is now part of Python, and it can be useful in some situations.

This tutorial will explore how Python's walrus operator works and will discuss situations where it can be used.

Become a Data Engineer

Build Python skills to become a professional data engineer.

Get Started for Free

What Is Python's Walrus Operator

The assignment expression, which uses the := operator, looks similar to the more common assignment statement, which uses the = operator. However, there's an important distinction between the two.

A statement is a unit of code that performs some action. An expression is a statement that can be evaluated to a value. Therefore, an expression returns a value, whereas statements that aren't expressions don't return any value.

Python's REPL (Read, Evaluate, Print, and Loop) displays the value of an expression as soon as it's evaluated. However, no value is shown when executing a statement that's not an expression:

>>> import random  # Not an expression
>>> 10 * 2  # An expression
20

The import statement doesn't evaluate to any value. However, 10 * 2 is an expression that evaluates to a value.

The assignment statement, which uses the = operator, assigns an object to a variable or another reference, but it doesn't return the value. The assignment expression, or walrus operator, performs the same action as the assignment statement but also returns the object:

>>> value = 10  # Assignment statement
>>> value
10
>>> (value := 20)  # Assignment expression
20

Note that the assignment statement doesn't return the value, unlike the assignment expression. Therefore, an assignment expression combines several operations:

  1. It evaluates the expression on the right-hand side of the := operator.
  2. It assigns this value to a variable name.
  3. It returns the value.

The parentheses are required syntax when using the assignment expression instead of an assignment statement, as in this example, to reduce ambiguity. There's more about the syntax requirements for the walrus operator later in this tutorial.

An assignment expression can be used anywhere expressions can be used in Python. Let's look at an example:

print(f"The number is {(value := 50)}")
print(value)
The number is 50
50

The variable name value is defined within the f-string in the first line. However, the integer is also returned directly to the curly braces in the f-string. The curly braces in f-strings must include an expression, which explains why an assignment statement can't be used.

Use Cases for Python’s Walrus Operator

Two common use cases for the walrus operator are simplifying and optimizing code.

Simplifying code

A common use case for the walrus operator is to simplify code where a variable would normally need to be defined before being used, such as in some conditional statements. Consider the following while loop:

import random
value = random.randint(1, 20)
while value < 18:
    print(value)
    value = random.randint(1, 20)
7
5
1
11
12
1
9

This code runs the while block as long as the random value generated is smaller than 18. The variable value needs to be defined before the while loop so it can be used in the while statement. A new random number is assigned to value at the end of the while block.

The assignment expression := can be used to reduce the lines of code and to call the random.randint() function in a single place in the program:

import random
while (value := random.randint(1, 20)) < 18:
    print(value)
1
9
2
4
9
15
11

A new random number is generated and assigned to value each time the while loop starts a new iteration.

Optimizing code

Let's look at another example using list comprehensions. Consider the following code, which filters a list of strings containing dates and creates a list of datetime.datetime objects containing only dates within a given year:

from datetime import datetime
def format_date(date_str):
    return datetime.strptime(date_str, "%Y-%m-%d")
dates = ["2024-01-01", "2022-12-31", "2024-06-15", "2023-08-23", "2024-11-30"]
formatted_dates = [
    format_date(date)
    for date in dates
    if format_date(date).year == 2024
]
print(formatted_dates)
[datetime.datetime(2024, 1, 1, 0, 0), datetime.datetime(2024, 6, 15, 0, 0), datetime.datetime(2024, 11, 30, 0, 0)]

The function format_date() accepts a string with a date in the yyyy-mm-dd format and returns a datetime.datetime object. One of the datetime.datetime object attributes is .year, which contains the year component of the date.

Only the three 2024 dates are included in the final list, which also contains datetime.datetime objects instead of strings. The list comprehension includes an if clause, which calls format_date(). However, format_date() is also called in the first expression in the list comprehension, which generates the values to add to the list. Calling the function with the same argument twice is inefficient, especially if the function is a bottleneck in the program's performance.

One option to avoid calling the same function twice is to call the function and assign it to a variable before using it. However, this can't be achieved with an assignment statement while still using a list comprehension. This solution requires a standard for loop:

from datetime import datetime
def format_date(date_str):
    return datetime.strptime(date_str, "%Y-%m-%d")
dates = ["2024-01-01", "2022-12-31", "2024-06-15", "2023-08-23", "2024-11-30"]
formatted_dates = []
for date in dates:
    formatted_date = format_date(date)
    if formatted_date.year == 2024:
        formatted_dates.append(formatted_date)
print(formatted_dates)
[datetime.datetime(2024, 1, 1, 0, 0), datetime.datetime(2024, 6, 15, 0, 0), datetime.datetime(2024, 11, 30, 0, 0)]

The walrus operator provides an alternative that's compatible with a list comprehension since the formatted date returned by the function can be assigned to a variable name and returned in the same expression:

from datetime import datetime
def format_date(date_str):
    return datetime.strptime(date_str, "%Y-%m-%d")
dates = ["2024-01-01", "2022-12-31", "2024-06-15", "2023-08-23", "2024-11-30"]
formatted_dates = [
    formatted_date
    for date in dates
    if (formatted_date := format_date(date)).year == 2024
]
print(formatted_dates)
[datetime.datetime(2024, 1, 1, 0, 0), datetime.datetime(2024, 6, 15, 0, 0), datetime.datetime(2024, 11, 30, 0, 0)]

The assignment expression in the list comprehension is the expression enclosed in parentheses, (formatted_date := format_date(date)). This expression calls the function format_date(), assigns its value to the variable formatted_date, and returns the value. Since the assignment expression evaluates to a datetime.datetime object, the code accesses the .year attribute, which is compared to 2024 using the equality operator.

The if clause in the list comprehension is executed before the expression that generates the value to store in the list. Therefore, the walrus operator is used in the if clause, and the variable defined in this assignment expression is used as the first expression in the list comprehension.

Python’s Walrus Operator Controversy

The assignment expression is not loved by all Python programmers. Some see it as a way of simplifying code, but others feel it makes code less readable and prefer the longer options. Readability can be subjective, so opinions vary on whether the walrus operator makes code more or less readable.

The last example in the previous section shows the trade-offs needed. Without the walrus operator, the code in this example needs an empty list to be initialized first, and then values are appended to it in a for loop. This solution is longer and less efficient than using list comprehensions, which are optimized for this job.

However, the standard for loop solution may be more readable for some programmers who prefer to write more code rather than use the walrus operator, especially if performance is not a concern.

Many coding style guides still recommend avoiding the assignment expression or only using it sparingly.

Python’s Walrus Operator: Syntax Rules

It's common to encounter syntax errors when initially exploring the walrus operator owing to its syntax rules.

To avoid confusion between the assignment statement = and assignment expression :=, there's no situation in which both options are syntactically valid. For this reason, it's often necessary to enclose the assignment expression in parentheses:

(value := 20)  # Valid
value := 20  # Invalid (SyntaxError)

The requirement to include the assignment expression in parentheses in this situation is the opposite of the assignment statement's requirement, which cannot be included in parentheses.

However, the assignment expression doesn't always need parentheses:

import random
if value := random.randint(0, 3):
    print(f"{value} is greater than 0")
1 is greater than 0

The assignment expression in the if statement generates a random number between 0 and 3 and assigns it to the variable value. The integers 1, 2, and 3 are truthy, and the code in the if block will run when these values are generated. However, when random.randint() returns 0, which is falsy, the if block is not executed.

The assignment statement is not valid after an if keyword. Therefore, there's no confusion in this situation, and parentheses aren't required.

This example also demonstrates another key point about the assignment expression. The scope of the variable assigned follows the normal LEGB rules. Therefore, the variable value is available everywhere in the global scope in this example:

import random
if value := random.randint(0, 3):
    print(f"{value} is greater than 0")
   
print(value)
2 is greater than 0
2

If an assignment expression is used within a function definition, the variable will only be available locally within the function. This is the same behavior as for variables created using an assignment statement.

This example can be modified to show another potential pitfall when using the walrus operator. Let's change this code to include a comparison operator in the if statement:

import random
if value := random.randint(0, 3) < 2:
    print(f"{value} is less than 2")
True is less than 2

The output shown hints at the problem with this code since value is the Boolean True rather than an integer. The walrus operator has the lowest precedence of all operators, and only the comma has lower precedence. Therefore, the less than operator < is evaluated first, and its output is assigned to value. Parentheses are required to deal with this situation:

import random
if (value := random.randint(0, 3)) < 2:
    print(f"{value} is less than 2")
0 is less than 2

The assignment expression is now evaluated first since parentheses have the highest precedence. The number returned by random.randint() is assigned to value, and it's used as the first operand for the less than operator.

Unlike the assignment statement, the walrus operator can only assign values to variable names and can't be used to assign values to subscripts or attributes:

(name := "James")  # Valid
points = {"James": 10, "Mary": 20}
(points["Sarah"] := 30)  # Invalid
class Article:
    pass
article = Article()
(article.title := "The Walrus Operator")  # Invalid

It's not possible to assign a value using a subscript or to an attribute using the walrus operator.

Conclusion

The assignment expression, which uses the := syntax and is often referred to as the walrus operator, is a relatively new addition to Python. The assignment statement, which uses the = operator, is the more common way of assigning a value to a variable name.

However, the walrus operator extends this assignment operation by also returning the value that's assigned, which makes this assignment an expression. Therefore, you can use the assignment expression wherever you can use other expressions in Python.

However, the Python community is split on the usefulness and readability of the walrus operator. For this reason, the assignment expression isn't used as often as other new additions to Python. It's great to know how to use this operator, but don't overuse it!

Become a Data Engineer

Prove your skills as a job-ready data engineer.

Photo of Stephen Gruppetta
Author
Stephen Gruppetta
LinkedIn
Twitter

I studied Physics and Mathematics at UG level at the University of Malta. Then, I moved to London and got my PhD in Physics from Imperial College. I worked on novel optical techniques to image the human retina. Now, I focus on writing about Python, communicating about Python, and teaching Python.

Topics

Learn Python with these courses!

Course

Introduction to Python for Developers

3 hr
18.1K
Master the fundamentals of programming in Python. No prior knowledge required!
See DetailsRight Arrow
Start Course
See MoreRight Arrow
Related

tutorial

Operators in Python

This tutorial covers the different types of operators in Python, operator overloading, precedence and associativity.
Théo Vanderheyden's photo

Théo Vanderheyden

9 min

tutorial

Python Logical Operators: A Hands-on Introduction

Python offers three logical operators: and, or, and not. These operators, also known as Boolean operators, evaluate multiple conditions and determine an expression's overall truth value.
Stephen Gruppetta's photo

Stephen Gruppetta

17 min

tutorial

Python lambda Tutorial

Learn a quicker way of writing functions on the fly with lambda functions.
DataCamp Team's photo

DataCamp Team

3 min

tutorial

Tuples in Python Tutorial

Learn to use and unpack Tuples in Python.
DataCamp Team's photo

DataCamp Team

3 min

tutorial

Usage of Asterisks in Python

Many Python users are familiar with using asterisks for multiplication and power operators, but in this tutorial, you'll find out additional ways on how to apply the asterisk.
Hafeezul Kareem Shaik's photo

Hafeezul Kareem Shaik

9 min

tutorial

How to Use the Python 'Not Equal' Operator

Comparing values in Python to check if they are not equal is simple with the not equal operator. Check out this quick tutorial on how to use the not equal Python operator, as well as alternatives for comparing floats.
Amberle McKee's photo

Amberle McKee

5 min

See MoreSee More