Arithmetic, Assignment and Comparison Operators

The seven arithmetic operators, the augmented assignment family and the six comparisons, including the chained comparison form that other languages do not have.

Arithmetic operators

OperatorMeaningExampleResult
+Addition7 + 29
-Subtraction7 - 25
*Multiplication7 * 214
/True division7 / 23.5
//Floor division7 // 23
%Modulo, the remainder7 % 21
**Exponentiation7 ** 249
total = 7
print(total / 2)      # 3.5   always a float
print(total // 2)     # 3     floors towards negative infinity
print(total % 2)      # 1
print(total ** 2)     # 49
print(-total // 2)    # -4    not -3

Practical uses of modulo

n = 18
print(n % 2 == 0)              # True  - is it even?
print(n % 3 == 0)              # True  - divisible by 3?

for i in range(10):
    if i % 3 == 0:
        print(i, "every third value")

seconds = 3725
print(seconds // 3600, "h", seconds % 3600 // 60, "m", seconds % 60, "s")

The same operators on other types

+ and * are defined for sequences as well, with a different meaning: joining and repeating.

print("ab" + "cd")        # abcd
print("ab" * 3)           # ababab
print([1, 2] + [3])       # [1, 2, 3]
print([0] * 4)            # [0, 0, 0, 0]

# print("ab" - "a")       # TypeError: - is not defined for strings
# print("ab" * "cd")      # TypeError: you cannot repeat by a string
Beware [[0] * 3] * 2. The outer repetition copies the reference, so both rows are the same list, and changing one changes both. Build nested lists with a comprehension instead.

Assignment operators

total = 100      # plain assignment

total += 20      # total = total + 20
total -= 30      # total = total - 30
total *= 2       # total = total * 2
total /= 4       # total = total / 4     -> becomes a float
total //= 3      # total = total // 3
total %= 7       # total = total % 7
total **= 2      # total = total ** 2

Augmented assignment is not only shorter. For mutable objects it is genuinely different, because it modifies the object in place rather than building a new one.

a = [1, 2]
b = a
a += [3]         # modifies the list both names share
print(b)         # [1, 2, 3]

a = [1, 2]
b = a
a = a + [3]      # builds a new list and rebinds only a
print(b)         # [1, 2]

The walrus operator

Since Python 3.8, := assigns a value and produces it, so a value can be captured inside a condition.

line = input("Command: ")
while line != "quit":
    print("You typed", line)
    line = input("Command: ")

# The same loop with the walrus operator, without repeating the input call.
while (line := input("Command: ")) != "quit":
    print("You typed", line)

Use it where it removes a genuine repetition. Do not use it to compress an already clear statement.

Comparison operators

OperatorMeaning
==Equal in value
!=Not equal in value
>Greater than
<Less than
>=Greater than or equal
<=Less than or equal

Every comparison produces a bool.

print(5 > 3)               # True
print("apple" < "banana")  # True  - dictionary order, character by character
print([1, 2] < [1, 3])     # True  - element by element, left to right
print((1, 2) == (1, 2))    # True

String comparison is by code point

print("Zebra" < "apple")   # True, because uppercase letters sort before lowercase
print("Zebra".lower() < "apple")   # False - compare case insensitively on purpose

Chained comparisons

Python allows a form that reads exactly like mathematics, and it is not merely syntactic sugar.

age = 25
print(18 <= age < 60)              # True

# It means this, with age evaluated only once:
print(18 <= age and age < 60)      # True

score = 87
if 80 <= score < 90:
    print("Grade B")

Chaining works for any comparison operators, and each operand is evaluated at most once. That matters when the middle term is a function call.

Comparing across types

print(1 == 1.0)          # True   - numeric types compare by value
print(1 == True)         # True   - bool is an int
print("1" == 1)          # False  - different types, never equal, no error
# print("1" < 1)         # TypeError: ordering across str and int is undefined

Equality across unrelated types returns False rather than raising. Ordering across unrelated types raises. That difference is deliberate: asking whether two things are equal is always a fair question, but asking which one is larger may be meaningless.

Common mistakes

  • Writing = where == was meant. In a condition Python raises a SyntaxError, which is a mercy compared with languages that accept it.
  • Assuming total /= 2 keeps an integer. It produces a float.
  • Comparing floats with ==.
  • Writing if x == True: instead of if x:.
  • Using [[0] * 3] * 2 for a grid.
  • Sorting mixed text and numbers and being surprised by a TypeError.

Best practices

  • Use chained comparisons for range tests; they read better and evaluate the middle term once.
  • Prefer // whenever the result is an index or a count.
  • Use augmented assignment for readability, and remember it mutates lists in place.
  • Compare booleans directly: if is_valid:, never if is_valid == True:.

Practice

  1. Convert 10 000 seconds into days, hours, minutes and seconds using only // and %.
  2. Explain why a += [3] and a = a + [3] can give different results for a shared list.
  3. Rewrite if x > 10 and x < 20 and x != 15: as clearly as you can.
  4. Predict print("10" > "9") and explain the answer.
  5. Write a condition that is true when a year is a leap year, using only %, and, or and comparisons.

Conclusion

Arithmetic in Python holds few surprises once /, // and % are clear. Comparisons hold one genuinely useful feature that most languages lack: chaining. Reach for it whenever you are testing a range.

Written by Lorens Mishra

Default administrator account created by the installer.

Continue reading

All Python notes →

Discussion

0 comments
Sign in to join the discussion.

No comments yet. Be the first to say something.