It’s interesting to share an example of using walrus operators that I saw on Twitter, the code looks like this:
(a, b := 2, 3) is particularly confusing, especially if you’ve written Go, and it’s likely that you intuitively think this expression is fine. But you can see through the output that it doesn’t match expectations at all, so what is wrong? Let’s take our time and analyze it.
This topic expands a lot and involves Python syntax, so let’s dive in step by step.
The Difference Between Expressions and Statements
A statement is one or more lines of code, and is a separate unit of the program. Expressions are special statements that can only contain identifiers (letters, numbers, underscores, etc.), literals (Python’s built-in constant types, such as strings, numbers, floating point numbers), and operators (add, subtract, multiply, divide, greater-than, less-than, different-or, remainder, etc.):
As in the example above,
1 + 2 is essentially a value (equal to 3),
a = 1 + 2 is just code logic, no value, just an assignment statement.
Assignment expressions and assignment statements
Let’s look at an example:
x = 1 is an assignment statement, which sets a specific value (1) to a specific storage address, which is marked with a specific variable name (x).
(y := 2) is an assignment expression, which adds the step
value to the assignment statement, which returns the result (2), so you can see the output
It is a syntax error not to add parentheses:
This is because in Python, assignment expressions and assignment statements are different syntaxes, and the following 2 ways are the correct syntax:
- assignment expressions use the
- assignment statements use the
Similarly, the following code is also syntactically incorrect:
So you cannot directly try to replace the
= operator with the
:= operator, you must add a parenthesis to assign a single value using an assignment expression.
The problem of converting assignment statements into expressions
We said that assignment expressions and assignment statements are syntactically different. The reason for this design is that converting an existing assignment statement into an expression is prone to bugs, which are exposed in C. For example:
This is a compliant code, but
(x = y) causes x to be reassigned to the value of y causing this judgment to be true and the output to be
x and y are equal (x = 8, y = 8). The reason for this is that the code does not use the comparison operator
==, which is a hidden error that is now explicitly thrown by programming languages like Python or Go.
It is possible (though not necessary) to achieve this logic with the correct walrus operator:
Why did you write the sentence
(a := 1)?
The answer is right here, and this added point is the problem with this confusing code. It’s really simple, try removing it:
This means that the code itself is not written correctly. In fact, this statement represents a tuple with three elements, a,
b := 2, 3. Here it says that a is not defined, but of course, it has never been assigned a. If you execute it in IPython, you can understand it.
The output is actually the result of returning the input data, so
(a, b := 2, 3) returns a tuple, the first element a is the result of the previous assignment, the second element is the result of the walrus operator, and the third is the literal 3.