Operators & Expressions

0/4 in this phase0/54 across the roadmap

📖 Concept

Python provides a rich set of operators that work intuitively with its data types. Understanding operators deeply — especially truthiness, short-circuit evaluation, and operator overloading — is essential for writing Pythonic code.

Arithmetic operators:

Operator Description Example Result
+ Addition 7 + 3 10
- Subtraction 7 - 3 4
* Multiplication 7 * 3 21
/ True division 7 / 3 2.333...
// Floor division 7 // 3 2
% Modulus 7 % 3 1
** Exponentiation 2 ** 10 1024

Comparison operators return bool and support chaining:

# Chained comparisons — unique to Python!
0 < x < 100        # Same as: 0 < x and x < 100
a == b == c         # All three are equal
1 <= grade <= 5     # Range check in one expression

Logical operators use English words, not symbols:

  • and — returns first falsy value, or last value if all truthy
  • or — returns first truthy value, or last value if all falsy
  • not — boolean negation

The walrus operator := (Python 3.8+) assigns and returns a value in one expression — useful in while loops and comprehensions.

Identity vs equality:

  • is / is not — checks if two references point to the same object
  • == / != — checks if two objects have the same value

Membership operators:

  • in / not in — checks if a value exists in a sequence or collection

💻 Code Example

codeTap to expand ⛶
1# ============================================================
2# Arithmetic operators
3# ============================================================
4print(7 / 3) # 2.3333... (true division — always returns float)
5print(7 // 3) # 2 (floor division — rounds toward negative infinity)
6print(-7 // 3) # -3 (NOT -2! Rounds toward negative infinity)
7print(7 % 3) # 1 (modulus)
8print(-7 % 3) # 2 (Python's modulus always returns non-negative for positive divisor)
9
10# Exponentiation
11print(2 ** 10) # 1024
12print(16 ** 0.5) # 4.0 (square root)
13print(pow(2, 10)) # 1024 (built-in function)
14print(pow(2, 10, 1000)) # 24 (modular exponentiation: 2^10 % 1000)
15
16# ============================================================
17# Comparison chaining (Pythonic!)
18# ============================================================
19age = 25
20
21# BAD (other languages style):
22if age >= 18 and age <= 65:
23 print("Working age")
24
25# GOOD (Pythonic):
26if 18 <= age <= 65:
27 print("Working age")
28
29# Multiple chaining
30x = 5
31print(1 < x < 10) # True
32print(1 < x < 10 < 100) # True (all comparisons must be true)
33
34# ============================================================
35# Logical operators: and, or, not
36# ============================================================
37# 'and' returns first falsy value, or last value if all truthy
38print(1 and 2 and 3) # 3 (all truthy, returns last)
39print(1 and 0 and 3) # 0 (first falsy value)
40print(1 and "" and 3) # "" (first falsy value)
41
42# 'or' returns first truthy value, or last value if all falsy
43print(0 or "" or 3) # 3 (first truthy value)
44print(0 or "" or []) # [] (all falsy, returns last)
45
46# Practical use: default values
47name = ""
48display_name = name or "Anonymous" # "Anonymous"
49print(display_name)
50
51# Short-circuit evaluation
52# 'and' stops at first falsy — right side not evaluated
53x = 0
54result = x != 0 and 10 / x # 10/x never executes (no ZeroDivisionError)
55print(result) # False
56
57# ============================================================
58# Walrus operator := (Python 3.8+)
59# ============================================================
60# Without walrus — compute twice or use temp variable
61data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
62
63# BAD: compute len() twice
64# if len(data) > 5:
65# print(f"List has {len(data)} items")
66
67# GOOD: compute once with walrus
68if (n := len(data)) > 5:
69 print(f"List has {n} items")
70
71# In while loops — read and check in one line
72import io
73buffer = io.StringIO("line1\nline2\nline3\n")
74while (line := buffer.readline()):
75 print(f"Read: {line.strip()}")
76
77# In list comprehensions — filter and transform
78numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
79results = [y for x in numbers if (y := x ** 2) > 20]
80print(results) # [25, 36, 49, 64, 81, 100]
81
82# ============================================================
83# Membership and identity operators
84# ============================================================
85fruits = ["apple", "banana", "cherry"]
86print("banana" in fruits) # True
87print("grape" not in fruits) # True
88
89# 'in' works with strings too
90print("hell" in "hello world") # True
91
92# 'in' with dictionaries checks keys (not values)
93user = {"name": "Alice", "age": 30}
94print("name" in user) # True (checks keys)
95print("Alice" in user) # False (not a key)
96
97# Identity checks
98a = [1, 2, 3]
99b = [1, 2, 3]
100print(a == b) # True (same value)
101print(a is b) # False (different objects)
102
103c = a
104print(a is c) # True (same object)
105
106# ============================================================
107# Bitwise operators
108# ============================================================
109a, b = 0b1010, 0b1100 # 10, 12
110
111print(f"a & b = {a & b:04b}") # 1000 (AND)
112print(f"a | b = {a | b:04b}") # 1110 (OR)
113print(f"a ^ b = {a ^ b:04b}") # 0110 (XOR)
114print(f"~a = {~a}") # -11 (NOT — two's complement)
115print(f"a << 2 = {a << 2}") # 40 (left shift)
116print(f"a >> 1 = {a >> 1}") # 5 (right shift)
117
118# Practical: using sets with bitwise operators
119set_a = {1, 2, 3, 4}
120set_b = {3, 4, 5, 6}
121print(set_a & set_b) # {3, 4} — intersection
122print(set_a | set_b) # {1, 2, 3, 4, 5, 6} — union
123print(set_a ^ set_b) # {1, 2, 5, 6} — symmetric difference
124print(set_a - set_b) # {1, 2} — difference

🏋️ Practice Exercise

Exercises:

  1. Predict the output without running: print(3 or 5), print(0 and 5), print("" or "hello" or "world"), print(1 and 2 and 3 and 0 and 5). Then verify.

  2. Rewrite these conditions using comparison chaining:

    • if x >= 0 and x <= 100
    • if a > b and b > c and c > d
    • if grade >= 90 and grade <= 100
  3. Use the walrus operator to simplify: read lines from a string using io.StringIO, process only lines longer than 5 characters, and collect the processed results.

  4. Write a function that takes a dictionary and a key, and returns the value if it exists and is not empty, otherwise returns a default. Use short-circuit evaluation with or.

  5. Demonstrate all set operations using bitwise operators (&, |, ^, -). Create two sets and show intersection, union, symmetric difference, and difference.

  6. Explain the difference between / and // with negative numbers. What is -7 // 2 and why?

⚠️ Common Mistakes

  • Confusing / (true division, returns float) with // (floor division). In Python 3, 7 / 2 is 3.5, not 3. Floor division // rounds toward negative infinity, so -7 // 2 is -4, not -3.

  • Using or for default values without understanding falsy values: count = user_count or 10 will replace 0 with 10, which may not be intended. Use count = user_count if user_count is not None else 10 for None-only checks.

  • Not understanding short-circuit evaluation — x and expensive_function() won't call the function if x is falsy. This is a feature, not a bug, and is commonly used for guard clauses.

  • Using is instead of == for value comparison. a is b checks identity (same object), not equality. Only use is for None, True, False, and sentinel objects.

  • Overusing the walrus operator — it can reduce readability when used in complex expressions. Use it for simple cases like while (line := f.readline()) and if (m := re.match(...)):. Don't nest walrus operators.

💼 Interview Questions

🎤 Mock Interview

Practice a live interview for Operators & Expressions