Operators and Expressions in Python
Arithmetic, floor division and modulo, precedence, augmented assignment, comparisons and the logical operators, plus the floating-point behaviour every programmer has to know.
Expressions and operators
An expression is any piece of code that produces a value: 3, price * 2, name + "!", age >= 18. An operator is the symbol that combines values (the operands) into a new value.
The result's type depends on the operator and the operands. Combining two ints with +, -, *, //, % or ** (with a non-negative exponent) gives an int. If either operand is a float, the result is a float. The / operator always gives a float.
Arithmetic operators
| Operator | Meaning | Example | Result |
|---|---|---|---|
| + | Addition | 7 + 2 | 9 |
| - | Subtraction | 7 - 2 | 5 |
| * | Multiplication | 7 * 2 | 14 |
| / | True division (always float) | 7 / 2 | 3.5 |
| // | Floor division | 7 // 2 | 3 |
| % | Remainder (modulo) | 7 % 2 | 1 |
| ** | Exponentiation | 7 ** 2 | 49 |
1print(7 + 2, 7 - 2, 7 * 2)2print(7 / 2, 8 / 2)3print(7 // 2, 7 % 2, 7 ** 2)4print(7 + 2.0, 2 ** -1)
9 5 14 3.5 4.0 3 1 49 9.0 0.5
Floor division and the remainder
a // b divides and rounds down to the nearest integer; a % b is what is left over. Together they satisfy a simple rule: (a // b) * b + a % b == a. The built-in divmod(a, b) returns both at once.
These two operators come up constantly:
- Unit conversion:
minutes = seconds // 60,seconds_left = seconds % 60. - Divisibility:
n % 2 == 0meansnis even;n % 5 == 0means a multiple of 5. - Digits:
n % 10is the last digit ofn, andn // 10removes it. - Wrapping around:
(index + 1) % lengthsteps through positions and returns to 0 at the end.
With negative numbers, "round down" means toward minus infinity, so -7 // 2 is -4, and the remainder takes the sign of the divisor: -7 % 2 is 1. The rule above still holds.
1seconds = 73842hours, rest = divmod(seconds, 3600)3minutes, secs = divmod(rest, 60)4print(hours, minutes, secs)56print(15 % 2 == 0, 16 % 2 == 0)7print(4096 % 10, 4096 // 10)8print((6 + 1) % 7)9print(-7 // 2, -7 % 2)
2 3 4 False True 6 409 0 -4 1
Precedence: which operator goes first
When an expression has several operators, precedence decides the order, as in school arithmetic: ** binds tightest, then unary minus, then *, /, // and %, then + and -. Operators with the same precedence run left to right, with one exception: ** runs right to left, so 2 ** 3 ** 2 is 2 ** 9.
Two results surprise people: -2 ** 2 is -4 (the power is applied before the minus sign), and 10 - 4 - 3 is 3, not 9.
When in doubt, add parentheses. They cost nothing and make the intended order obvious to readers.
1print(2 + 3 * 4)2print((2 + 3) * 4)3print(2 ** 3 ** 2)4print(-2 ** 2, (-2) ** 2)5print(10 - 4 - 3)6print(100 / 10 / 5)
14 20 512 -4 4 3 2.0
Augmented assignment
Updating a variable from its own value is so common that every arithmetic operator has a shorthand: x += 5 means x = x + 5. The same pattern works for -=, *=, /=, //=, %= and **=.
These are statements, not expressions: they update the name and produce no value, so print(x += 1) is a syntax error. Python also has no ++ or --; write count += 1.
1balance = 1002balance += 503balance -= 304balance *= 25print(balance)6balance //= 77print(balance)8label = "ha"9label *= 310print(label)
240 34 hahaha
Floating-point numbers are approximations
Floats are stored in binary with about 15–17 significant decimal digits. Most decimal fractions, including 0.1, cannot be stored exactly, just as 1/3 cannot be written exactly in decimal. The tiny errors are normally invisible but show up in comparisons and repeated sums.
Three habits avoid trouble:
- Never compare floats with
==. Usemath.isclose(a, b)or check that the difference is very small. - Round only for display, with
round(x, 2)or an f-string such asf"{x:.2f}", and keep full precision in calculations. - Use integers for money, counting cents, or the
decimalmodule when exact decimal arithmetic is required.
This is a property of binary floating point in every mainstream language, not a Python bug.
1import math23print(0.1 + 0.2)4print(0.1 + 0.2 == 0.3)5print(math.isclose(0.1 + 0.2, 0.3))6print(round(0.1 + 0.2, 2))7price_cents = 1999 * 38print(f"{price_cents // 100}.{price_cents % 100:02d}")
0.30000000000000004 False True 0.3 59.97
Comparison operators
Comparisons produce a bool: == (equal), != (not equal), <, <=, > and >=. Numbers compare by value, so 3 == 3.0 is True. Strings compare character by character using each character's code, so "apple" < "banana" is True, but every upper-case letter sorts before every lower-case one: "Zebra" < "apple" is also True.
Python allows chained comparisons: 0 <= score <= 100 means 0 <= score and score <= 100, written the way a mathematician would.
Use == to compare values. The is operator checks whether two names refer to the very same object; reserve it for None (x is None).
`"10" < "9"` is True because strings compare character by character and "1" comes before "9". Convert numeric text to numbers before comparing.
1score = 872print(score >= 50, score == 100, score != 100)3print(0 <= score <= 100)4print(3 == 3.0)5print("apple" < "banana", "Zebra" < "apple")6print("10" < "9", 10 < 9)
True False True True True True True True False
and, or, not
The logical operators combine conditions:
a and bis true only when both are true.a or bis true when at least one is true.not aflips a truth value.
Precedence is not, then and, then or, so a or b and c means a or (b and c). Parentheses keep mixed conditions readable.
Both and and or short-circuit: they stop as soon as the answer is known. In x != 0 and 10 / x > 1, the division never runs when x is 0. They also return one of their operands rather than a plain True/False: or returns the first truthy operand, which gives the common default-value idiom name = typed_name or "Guest".
Truth table
| a | b | a and b | a or b | not a |
|---|---|---|---|---|
| True | True | True | True | False |
| True | False | False | True | False |
| False | True | False | True | True |
| False | False | False | False | True |
1age = 202has_ticket = True3print(age >= 18 and has_ticket)4print(age < 12 or age >= 65)5print(not has_ticket)67x = 08print(x != 0 and 10 / x > 1)9typed_name = ""10print(typed_name or "Guest")
True False False False Guest
Beyond the operators: the math module
Operators cover arithmetic; the standard library's math module adds the rest. import math at the top of a program gives you math.sqrt, math.floor, math.ceil, math.pi, math.gcd and many more. A few useful built-ins need no import at all: abs(), min(), max(), round() and pow().
Modules get their own lesson later in the course; for now, treat import math as "make the math tools available".
1import math23print(math.sqrt(144), math.floor(2.7), math.ceil(2.1))4print(round(math.pi, 4))5print(abs(-12), min(4, 9, 1), max(4, 9, 1))6print(math.gcd(84, 36))
12.0 2 3 3.1416 12 1 9 12
Check your understanding
What does `print(17 // 5, 17 % 5)` print?
Practice
Both problems are pure arithmetic with // and %: turn a number of seconds into clock time, and split a bill into fair shares without losing a cent.
Seconds to Clock Time
Reveal Solution & AnalysisHide Solution
Split the Bill
Reveal Solution & AnalysisHide Solution
Quick Syntax & Reference Sheet
| Concept / Rule | Syntax / Usage |
|---|---|
| True division / floor division | 7 / 2 == 3.5; 7 // 2 == 3 |
| Remainder and both at once | 7 % 2 == 1; divmod(7, 2) == (3, 1) |
| Power | 2 ** 10 == 1024 |
| Augmented assignment | total += price |
| Chained comparison | 0 <= x <= 100 |
| Even test | n % 2 == 0 |
| Float comparison | math.isclose(a, b) |
| Default value | name = typed or "Guest" |
Common Pitfalls & Developer Mistakes
Using / when an integer is needed
Why it happens: 8 / 2 is 4.0, a float, which then fails where an int is required (for example as a list index).
Comparing floats with ==
Why it happens: Rounding errors make mathematically equal results differ in the last bits.
Writing x = x++ or x++
Why it happens: Python has no increment operator; ++x is just +(+x).
Writing if x == 1 or 2:
Why it happens: This means (x == 1) or 2, and 2 is always truthy, so the condition is always true.