Operators and precedence
Predict the result of Python expressions using precedence, chained comparisons, and the way and and or return operands.
What you will learn
- Predict evaluation order using Python's precedence rules
- Write chained comparisons such as 0 < x < 10
- Explain what and and or actually return
- Use the walrus operator to name a value inside an expression
On this page
Most Python operators behave the way arithmetic class taught you. A handful do not, and those are the ones that cause bugs: -2 ** 2, a comparison that chains, and and returning something that is not a boolean.
The fundamentals lesson explains precedence and short-circuiting in general. This lesson covers how Python applies them.
Precedence in practice
From tightest to loosest, the groups you will meet most are: **, unary -, then * / // %, then + -, then comparisons, then not, and and or. When in doubt, add parentheses. They cost nothing and tell the next reader what you meant.
Start with arithmetic:
print(2 + 3 * 4)print(-2 ** 2)print((-2) ** 2)print(2 ** 3 ** 2)print(10 - 4 - 3)14-445123-2 ** 2is-(2 ** 2), because**binds tighter than a unary minus on its left.**groups right to left, so2 ** 3 ** 2is2 ** (3 ** 2), which is 512.- Subtraction groups left to right:
10 - 4 - 3is(10 - 4) - 3.
Comparisons produce True or False, and not, and and or combine them:
print(not 1 == 2)print(1 + 2 == 3 and 4 > 3)TrueTruenot 1 == 2 is not (1 == 2), because comparisons bind tighter than not. The second line works out both comparisons first, then combines them with and.
Chained comparisons
Python lets you chain comparisons the way mathematics does. a < b < c means a < b and b < c, with b evaluated only once.
age = 25print(18 <= age < 65)print(1 < 3 < 2)TrueFalseThe first line asks whether age lies in the range from 18 up to, but not including, 65. The chain 1 < 3 < 2 fails on its second link.
and and or return operands
and and or do not return True or False. They return one of their two operands:
a or breturnsaifais truthy, otherwiseb.a and breturnsaifais falsy, otherwiseb.
Here “truthy” and “falsy” mean what they sound like: 0 and the empty string "" count as false, and almost everything else counts as true. Lesson 13 covers the full rules.
print(0 or "default")print("name" or "default")print(5 and 7)print("" and "never")defaultname7Both operators stop as soon as the answer is known, which is called short-circuiting. That is why "" and "never" gives the empty string: the right side is never looked at. The blank last line in the output is that empty string.
This makes value or default a popular way to supply a fallback:
nickname = ""print(nickname or "anonymous")anonymousBe careful, though: it replaces every falsy value, including 0 and "", not just missing ones.
The walrus operator
The assignment expression :=, nicknamed the walrus, binds a name in the middle of an expression. It exists since Python 3.8.
print((squared := 7 * 7) + 1)print(squared)5049The part in parentheses worked out 7 * 7, bound the name squared to the result, and then handed that value to the + 1. Afterwards squared is an ordinary name. You will find the walrus most useful inside the conditions of if and while, once you have met them, where it avoids calling something twice. Wrap it in parentheses unless it stands alone, and use it sparingly. If a plain assignment on its own line reads better, use that.
Common pitfalls
x == 1 or 2. This parses as(x == 1) or 2, which is always truthy. Writex == 1 or x == 2.- Misusing a chain.
1 < x > 0is legal but confusing. Keep chains in one direction. - Reading
a != b != cas “all three differ”. It meansa != b and b != c, soaandcmay still be equal. - Using
orfor defaults when0is valid.count or 10turns a real0into10.
Work out the output of every line on paper, then run the file and compare. Input: none. Expected output: ten lines.
print(3 + 4 * 2 ** 2)print(-3 ** 2)print(2 * 3 % 4)print(7 // 2 * 2)print(not True or True)print(1 < 2 < 3 < 3)print(0 or "" or "x")print(10 / 4 * 2)print(2 + 3 > 4 and 1 + 1 == 2)print("a" * 2 + "b" * 3)Show solution
19-926TrueFalsex5.0TrueaabbbKey steps: 2 ** 2 is 4, times 4 is 16, plus 3 is 19. -3 ** 2 is -(3 ** 2). 2 * 3 % 4 goes left to right: 6 % 4 is 2. not True or True is (not True) or True. The chain 1 < 2 < 3 < 3 fails on its last link. 0 or "" or "x" skips two falsy values and returns "x". 10 / 4 * 2 is 2.5 * 2, a float.
Predict the three lines this prints, then run it. Input: none. Expected output: three lines.
x = 3print(x == 1 or 2)print(x == 1 or x == 2)print(1 < x < 5)Show solution
2FalseTruex == 1 or 2 is (x == 1) or 2. The left side is False, so or returns its right operand, 2. That is a truthy value, so the test would pass for any x. The second line is the correct way to ask “is x 1 or 2”. The third is a chained comparison.
Summary
**binds tighter than a unary minus, and**groups right to left. Use parentheses when unsure.a < b < cis a chained comparison.andandorreturn one of their operands.:=names a value inside an expression and has existed since Python 3.8.
Next: strings.