Introduction

First proposed back on the 28th Feb 2018 in PEP 572 and implemented by Emily Morehouse, the upcoming release of Python 3.8 brings with it  a new language feature, Assignment Expressions. This new feature exposes the functionality to assign a value to a variable within a Python expression, evaluate the result, then re-use the variable within it’s scope.  The := operator used to define an assignment expression has become colloquially known as the Walrus Operator.

During discussion of this PEP, the operator became informally known as "the walrus operator". The construct's formal name is "Assignment Expressions" (as per the PEP title), but they may also be referred to as "Named Expressions" (e.g. the CPython reference implementation uses that name internally).

The primary benefit that assignment expressions offer is more concise code, reducing the need for extra lines of code when assigning the result of an expression to a variable before evaluation.


At a high level, assignment expressions work by evaluating the expression on the right-hand side of the := (walrus) operator and assigning it to the variable on the left-hand side of the operator. This provides the ability to both evaluate the boolean result of the expression and assign a value from it for reuse all in one simple expression.


E.g. in the below example, my_dict.get("name")  checks my_dict for the existence of a value with a key of name. The dictionary has no value with that key so None is returned and assigned to val using the walrus operator. In the context of a conditional statement val is then evaluated and acted on accordingly and possibly re-used within it's scope.

This is a very trivial example to illustrate the rationale behind assignment expressions.

Controversy

As many people are likely already aware, PEP 572 which proposed this new language feature bought with it a significant amount of controversy amongst the Python core developers and the community as a whole.

Ultimately this resulted in Guido van Rossum the creator and long time BDFL (“Benevolent Dictator for Life”) of Python stepping away from the role of BDFL, as outlined in his message in the Python mailing list titled Transfer of Power on the 12th of July 2018.

Syntax & Valid Uses

As described in PEP 572…

In most contexts where arbitrary Python expressions can be used, a named expression can appear. This is of the form NAME := expr where expr is any valid Python expression other than an unparenthesized tuple, and NAME is an identifier.

Essentially this means that an assignment expression can be used (almost) anywhere that a legal Python expression could be used prior to the implementation of assignment expressions with a few exceptions.

The cases where an assignment expression is legal are simply to avoid any ambiguity between the now two different syntaxes of assigning a value in Python.  The intention here is to not provide any confusion over which is the correct syntax for a given scenario.

The following uses of assignment expressions are disallowed (for good reason).

  • At the top level of an expression statement.
  • At the top level of the right hand side of an expression statement.
  • As the value of a keyword argument in a function call.
  • As a top level default value in a function definition.
  • As annotations on function arguments, return values or variable assignments.
  • Unparenthesized expressions within lambda functions.

It is possible to workaround these limitations however by wrapping the assignment expression in parentheses where it would normally be disallowed. This is probably a bad idea however. The Python core dev team have put these restrictions in place for good reason, to avoid ambiguous and complicated code.  As can be seen in the following examples of these disallowed uses add nothing in terms of readability and in a lot of cases make the code very difficult to comprehend.

Note:These examples have been reproduced from the exceptional cases section of PEP572

One other notable rule is that an assignment expression in the context of an f-string is required to be wrapped in parentheses.

f"Hello, {(name := get_name())}!. Hello, again {name}!"

Scope of the expressions target

The addition of assignment expressions to Python does not add any new behaviour with regards to the scope of an assignment expressions target variable.

This is beneficial and makes assignment expressions easy to pick up, even for new developers as it fits in with existing behaviour of Python.

Performance Considerations

For the most part, there are no differences in performance when using assignment expressions.  Performance improvements are possible using assignment expressions by removing duplicate computations of values.

One example is when computing a value to perform filtering within a list comprehension.

An example of this is computing the power of 2 for a range of numbers and then filtering only round numbers in the resulting list of values. By using an assignment expression within the list comprehension to store the computed value of pow(x, 2). There is a runtime improvement of almost 20% (206ms) in the below example.

Conclusion

Assignment expressions and the walrus operator are a valuable, refreshing addition to Python.

The care given by the Python core development team in providing an easy to learn feature. Providing a simple to use operator with little new syntax is great to see.
Provided assignment expressions are used in a pragmatic manner they will provide improved readability and conciseness of code. In some instances, enhanced performance is also possible by reducing the need to recompute a value.

The only caveat to this is that being a new language feature, there is the potential that many developers will be unfamiliar with the syntax and behaviour. In which case the readability of code could be reduced for such users.