Since the version 3.8 Python has a new operator, officially called the assignment expression operator :=
, because of its looks the Python community gave it the name walrus operator. In this article, you will learn what the walrus operator does, how to use it, and how to improve the quality of your code with the walrus operator.
Python Assignments and Expressions
When a variable (in any programming language) gets assigned a value, it is called an assignment. In Python, the assignment operator is the equal sign =
. When using the assignment operator, on the right-hand side is the variable that gets assigned a value and on the left-hand side is the value:
1
2
3
a = 42
b = None
c = ['a', 'b', 'c']
However, the value that gets assigned to the variable does not have to be explicit, the value can come from an expression. In programming languages, an expression is a valid combination of variables, literals, operators, and functions which produces a value. The following are all examples of expressions in Python:
1
2
3
4
5
6
7
8
23 - 42
# > -19
'a' + 'c'
# > 'ab'
str(sum([1, 2, 3])) * 3
# > 666
When using the Python interactive mode or IPython, you will notice that after entering an expression a value is printed before a new prompt >>>
, while there appears no value after an assignment was entered:
1
2
3
4
>>> 1+2
3
>>> a = 3
>>>
Expressions are often nested, such as long formulas, where the Python operator precedence determines which expression is evaluated before the others. Using parenthesis, the order of evaluation of expressions can be set manually.
1
2
3
4
>>> 1+2*3
7
>>> (1+2)*3
9
What does the Python Walrus Operator do?
Now that you know what an assignment and expression is in Python, let’s take a look at the assignment expression operator or walrus operator. The walrus operator (:=
) combines a variable assignment with an expression. While the normal assignment operator =
does not return any value, not even None. The :=
operator first assigns the value to a variable and then returns the assigned value:
1
2
>>> (a := 23)
23
Where should I use the Python Walrus / := Operator?
The Python walrus operator is especially useful when you want to check a condition and also use the value that is checked later on in your program. Take a look at the program below, the function distance
returns the distance between two numbers regardless of their sign. The distance
function is called twice, once when the condition of the if
-clause checked and then a second time to print the distance:
1
2
3
4
5
def distance(a, b):
return abs(a-b)
if distance(2, 5) < 4:
print(f"distance {distance(2, 5)} is smaller than 4.")
This code has two problems. The first one is that the distance
could be a function that uses a considerable amount of processing power, which would essentially double the runtime of the program. The second problem is maintainability. When distance
is replaced with another function, there are two places that have to be changed, which could introduce a bug that is difficult to find when only one place was actually changed. An easy fix for this is to introduce a variable d
which gets assigned the return value of distance
:
1
2
3
4
5
6
7
def distance(a, b):
return abs(a-b)
d = distance(2, 5)
if d < 4:
print(f"distance {d} is smaller than 4.")
However, the distance
of the numbers 2
and 5
should be associated with the if
-clause and in the code above d
declared outside the if
-clause. And here comes the :=
operator into play. By using the assignment expression operator, d
can be assigned with the value returned from distance
and at the same time the condition is checked in the if
-clause:
1
2
3
4
5
def distance(a, b):
return abs(a-b)
if (d := distance(2, 5)) < 4:
print(f"distance {d} is smaller than 4.")
This makes the code a lot more understandable and maintainable.
Another example to improve the readability of your code using the :=
operator are while
loops. The following program increases the value of a
until the distance between a
and b
is equal or less than 3:
1
2
3
4
5
6
7
8
9
10
11
12
def distance(a,b):
return abs(a-b)
a = 0
b = 8
while True:
if (d := distance(a,b)) > 3:
print(f"the distance between a and b is {d}")
a += 1
else:
break
The while loop above uses an infinite while loop with a break
statement nested inside an if
-else
-clause. The code works correctly. However, it is a bit messy. Using the :=
operator, you can improve it quite a bit:
1
2
3
4
5
6
7
8
9
def distance(a,b):
return abs(a-b)
a = 0
b = 8
while (d := distance(a,b)) > 3:
print(f"the distance between a and b is {d}")
a += 1
By moving the if
-clause condition with the :=
operator into the while
loop condition, the code is instantly more readable and the context of d
is immediately clear to other people and who might read your code in the future.
Witness and Counter Example using the Python Walrus / :=
Operator
The :=
operator cannot only improve the readability of your code, it also enables an entirely new use case with the any()
, all()
, and list comprehensions.
Consider the following list of strings containing names:
1
names = ["Olivia", "Emma", "Sophia", "Isabella", "Mia"]
Using the any()
and all()
functions together with list comprehensions, you can check if any or all of the names fulfil a given condition:
1
2
3
4
5
6
7
8
9
10
11
12
>>> any("mm" in name for name in names)
True
>>> any(len(name) < 3 for name in names)
False
>>> all(name.endswith("a") for name in names)
True
>>> all("i" in name for name in names)
False
In the above examples, it is first checked if any of the names
contains the string mm
which is True
for the name "Emma"
. In the second example, any()
is used to check if any of the names has less than 3 characters, which is False
for all names
. Using all()
it is first checked if all names
end with a
which is True
for all of them. Lastly, all()
is used to check if all names
contain the character "i"
which is False
.
While the examples tell you that there is an element or all elements of the list that fulfil a condition, you still don’t know which element. Here comes the :=
into play:
1
2
if any("mm" in (witness := name) for name in names):
print(f"{witness} contains 'mm'")
Inside the list comprehension, the variable witness
gets assigned the value of name
for every element in names
until one fulfills the condition. Because any()
uses short-circuit evaluation, the first element which fulfills the condition is assigned to witness
. If you haven’t heard about short-circuit evaluation, you can read up on it in my article on conditional statements if, else and elif.
Making use of short-circuit evaluation and the all()
function allows you also to find counter examples in a list:
1
2
if all("i" in (counter_example := name) for name in names):
print(f"{counter_example} does not contain 'i'")
In the code above, the first element which does not contain the character i
is assigned to the variable counter_example
.
With this article on the Python :=
operator, you have learned all how to improve the readability and maintainability of your code and how to use the :=
operator cleverly to find witnesses and counter examples in lists. Make sure to get the free Python Cheat Sheets in my Gumroad shop. If you have any questions about this article, feel free to join our Discord community to ask them over there.