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:
they write:
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
can be written as:
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
can be written as much shorter:
Another example when reading all lines in a file:
can be written succinctly as:
Example 3: Reusing a value that's expensive to compute
can be written as:
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.
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:
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!