The Hidden Teaching: The Flow of Assignment
Just as a master potter knows that some steps must precede others regardless of the order they're written, a seasoned Python developer understands that a seemingly simple assignment is not a singular event. It's a flow. The value does not flow from left to right; it flows from right to left.
Part 1: Assignment Chains
Consider a chain of assignments:
This may appear to assign x + 2
to x
, y
, and z
simultaneously. But Python does not work that way. It evaluates this expression from right to left.
The expression
x + 2
is evaluated. The value12
is assigned to the variablez
.This assignment itself returns the value that was assigned, which is
12
.This returned value
12
is then assigned toy
.This new assignment also returns the value
12
, which is then assigned tox
.
The operation is sequential. The rightmost value is the source and it moves leftward like water flowing down a stream. This is true for all assignment operators.
Part 2: Identity and Comparisons
Consider the following assignment chain:
list2 = list3 = list1 = [1,2,3]
On the surface, this appears simple. But because assignment chains are right-to-left, they create a single list object [1,2,3]
and assign a reference to that same object to list1
, then to list3
, and finally to list2
.
This is not a copy. It's a shared reference.
Modifying one of these variables will affect all others. We can confirm this by checking the identity of the objects using the id()
function.
Part 3: Comparison Chains
The same principle applies to chained comparison operators such as <
, >
and ==
.
1 < x < 10
However, unlike the assignment operator, a comparison chain is not evaluated from right to left. The interpreter performs a series of distinct comparisons and joins them with an implicit and
operator.
The expression 1 < x < 10
is not shorthand for a single operation. It is shorthand for two separate operations:
(1 < x) and (x < 10)
This is an important distinction. The value of x
is only evaluated once. The interpreter is smart enough to perform the minimal number of checks. If 1 < x
is False
, the expression x < 10
is not evaluated at all because the entire and
expression will be False
. This is known as short-circuiting and **** you can use this to your advantage when writing logical expressions:
(high_probability_of_being_false) and (low_probability_of_being_false)
If you write the expression with the higher likelihood of being False
first, then you avoid the second expression from being executed. This is something you might have to consider when writing performance sensitive code.
Part 4: Chained Comparisons with Side Effects
What about chained comparisons containing functions with side effects? While Python evaluates a < b < c
as (a < b) and (b < c)
, what happens if b
is the result of a function call? Consider the following example:
The output will be Getting B's value...
followed by The truth holds
. The function get_val_b
is called once and its returned value 5
is used for both 1 < 5
and 5 < 10
.
The comparison is evaluated as a logical and
, but the function call that produces the shared value for both comparisons is only executed once.
Firing the pot
The master potter’s lesson was simple. The order in which instructions are given are not the order in which they must be executed. In Python, chained instructions are executed according to the following rules:
Assignment chains are a sequential flow of value from right to left.
Comparison chains are a logical union of individual comparisons.
When you chain operators you are not simply performing a single operation. You are creating a silent understanding of how values will flow and how logic will be judged.
If you enjoyed reading this post, consider sharing it with your friends!
Top comments (0)