All Posts

Walrus operator in Python 3.8: a primer

Walrus operator in Python 3.8: a primer

Assignment expressions (:=), or the "walrus" operator, have been the most talked about feature to be introduced in the latest version of Python. The new addition to the language was proposed in PEP 572. In this post, we look at the rationale behind assignment expressions, and understand how to use it with various examples.

Background

The primary rationale behind introducing assignment expressions, as stated in the PEP, is the observation that programmers want to save lines of code, and would even repeat a subexpression (and thereby slow down the program) in order to do so.

So instead of writing:

 
match = re.match(data)
group = match.group(1) if match else None


they write:

 
group = re.match(data).group(1) if re.match(data) else None

Assignment in expressions make it easier to write code constructs where a value calculated is re-used as part of some condition later, and help make the intent of the code's author clearer. Languages like C and Go, among others, already support a functionality like this.

Where to use the Walrus operator

Let's have a look at few examples on how to use walrus operator in Python:

Example 1: When a calculated value is used as part of a condition later

 
match = pattern.search(data)
if match is not None:
    do_something(match)

can be written as:

 
if (match := pattern.search(data)) is not None:
do_something(match)


The above piece of code can be read as: if match, which becomes pattern.search of data, is not None, do_something of match.

Example 2: When reading a generator resource that exhausts
 
chunk = resource.read(8192)
while chunk:
    process(chunk)
    chunk = resource.read(8192)


can be written as much shorter:

 
while chunk := resource.read(8192):
process(chunk)

Another example when reading all lines in a file:

 
line = f.readline()
while line:
    do_something(line)
    line = f.readline()


can be written succinctly as:

 
while line := f.readline():
do_something(line)

Example 3: Reusing a value that's expensive to compute
 
filtered_data = [
  f(x) for x in data
  if f(x) is not None
]


can be written as:

 
filtered_data = [
y for x in data
if (y := f(x)) is not None
]


This saves re-calculation of f(x) and can improve performance of the program, while still keeping the line count to the same.

The authors of the PEP have also rationalized the feature by showing real-world examples from the Python standard library where using the walrus operator would save lines and make the intent clearer.

Where not to use the Walrus operator

Assignment expressions are not allowed in certain cases to avoid ambiguities — such as when used at the top level of an expression statement without parentheses. This simplifies the choice for the user between an assignment statement (=) and an assignment expression (:=) — there is no syntactic position where both are valid.

 
y := f(x)  # INVALID
(y := f(x))  # Valid, though not recommended

y0 = y1 := f(x)  # INVALID
y0 = (y1 := f(x))  # Valid, though discouraged


foo(x = y := f(x))  # INVALID
foo(x=(y := f(x)))  # Valid, though probably confusing

Things to keep in mind

  • An assignment expression does not introduce a new scope, and is bound by the current scope. If the current scope contains a nonlocal or global declaration for the target, the assignment expression honors that.
  • There is one special case: an assignment expression occurring in a list, set or dict comprehension or in a generator expression binds the target in the containing scope, honoring a nonlocal or global declaration for the target in that scope, if one exists. So it's possible to do something like this:
 
total = 0
partial_sums = [total := total + v for v in values]
print("Total:", total)


However, an assignment expression target name cannot be the same as a for-target name appearing in any comprehension containing the assignment expression.

What are your opinions on the Walrus operator? Do you think it is going to simplify writing code, or rather decrease the readability? Let us know @DeepSourceHQ!

Get started with DeepSource

DeepSource is free forever for small teams and open-source projects. Start analyzing your code in less than 2 minutes.

Newsletter

Read product updates, company announcements, how we build DeepSource, what we think about good code, and more.

Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.