Koan 9: The Unfired Pot
Exploring chained operations and order of evaluation in python expressions
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. Python evaluates the right-hand side first and binds that result to each target from left to right.
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. The expression x + 2 is evaluated once, producing the value 12, which is then sequentially bound to z, y, and x. Assignment in Python is a statement, not an expression, so it does not return a value during this process.
Part 2: Identity and Comparisons
Consider the following assignment chain:
list2 = list3 = list1 = [1,2,3]On the surface, this appears simple. It creates a single list object [1, 2, 3] and binds list1, list3, and list2 to that same object.
This is a shared reference, not a copy.
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 of sharing values does not apply to chained comparison operators such as <, > and ==.
1 < x < 10This expression is not evaluated from right to left. Instead, 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)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 evaluate the right-hand side once and bind that result sequentially to each target.
Comparison chains are logical combinations of individual comparisons.
When you chain operators you are creating a silent understanding of how values will flow and how logic will be judged.
New here? Python Koans is a Python newsletter that helps you learn Python through short puzzles. Catch up on the last issue here:






The part about assignments is completely bogus. First, no, assignments don't return a value at all, they are not expressions but statements (walrus is a different thing, but it cannot be nested in this way). Python is not C.
But even if they were, Python semantics is opposite. Assignment targets are processed from left to right, which you can easily see by instrumenting setattr, in the same way you instrumented getting the value of b in part 3.