I had the following line in a loop occurring during the initialization of a singly linked list class:
previous = previous.pointer = Node(item, None)
The intended semantics was what I can obtain with:
previous.pointer = Node(item, None)
previous = previous.pointer
What I found out using pdb is that previous
gets reassigned to the new Node
object. And the (former) previous
's pointer attribute is unchanged.
I couldn't find documentation about the expected behaviour of this kind of assignment.
Assignment statements in Python do not copy objects, they create bindings between a target and an object. For collections that are mutable or contain mutable items, a copy is sometimes needed so one can change one copy without changing the other.
Assignment expressions were added to Python in version 3.8. The general idea is that an assignment expression allows you to assign to variables within an expression. This operator has been called the "walrus operator", although their real name is "assignment expression".
An assignment statement evaluates the expression list (remember that this can be a single expression or a comma-separated list, the latter yielding a tuple) and assigns the single resulting object to each of the target lists, from left to right.
The code demonstrates that simultaneous assignment really is simultaneous. The value for a does not change before the value of b , so b gets the original value of a , and we can switch the values without using an interim step of creating a temporary (and otherwise useless) variable.
This is well explained in the documentation:
An assignment statement evaluates the expression list (remember that this can be a single expression or a comma-separated list, the latter yielding a tuple) and assigns the single resulting object to each of the target lists, from left to right.
(emphasis mine)
Where the term target_list
is used in the grammar as follows:
assignment_stmt ::= (target_list "=")+ (expression_list | yield_expression)
(Note the +
sign after the first parenthesis - this allows chain assignments)
Thus, the resulting semantics:
target_list1 = target_list2 = expression
is equivalent to:
target_list1 = expression
target_list2 = expression
There is no way of confusing what is being assigned (evaluates the expression list) with what is the target of the assignment, because assignment is a statement, not an expression. Hence, all with =
in it, will not be treated as an expression - only the right most part. Next, all assignment statements will be processed left to right (i.e. their target lists will have the expression's value assigned).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With