The Story That Explains Operators
In Python, operators are those kitchen tools. Numbers, strings, and booleans are your ingredients. Operators are the symbols that do something with them — add them, compare them, combine them, invert them. Without operators, your data just sits there. With operators, it becomes a working program.
You cannot build any meaningful program without operators. Every calculation, every decision, every loop — powered by operators working behind the scenes.
An operator is a special symbol that performs an operation on one or more values (called operands). In the expression 5 + 3, the plus sign + is the operator, and 5 and 3 are the operands. Python has seven categories of operators, each designed for a specific purpose.
Python operators fall into seven neat categories: Arithmetic, Comparison, Logical, Assignment, Bitwise, Membership, and Identity. Each category solves a different class of problem — from doing maths to checking if a value exists in a list. Master them, and you master the mechanics of Python.
The Seven Categories of Python Operators
Before diving into each category, here is the complete map. Every operator you will ever use in Python belongs to one of these seven groups.
Arithmetic Operators — The Mathematics Toolkit
Arithmetic operators are the ones you learned in primary school — plus a few Python-specific bonuses. They work on numbers (int and float) and some behave surprisingly well on strings and lists.
| Operator | Name | Example | Result | Notes |
|---|---|---|---|---|
| + | Addition | 10 + 3 | 13 | Also joins strings and lists |
| - | Subtraction | 10 - 3 | 7 | Also negates: -x |
| * | Multiplication | 10 * 3 | 30 | Repeats strings/lists: "ab"*3 |
| / | Division | 10 / 3 | 3.333... | Always returns a float |
| // | Floor Division | 10 // 3 | 3 | Drops the decimal (rounds down) |
| % | Modulo | 10 % 3 | 1 | The remainder after division |
| ** | Exponentiation | 10 ** 3 | 1000 | 10 to the power of 3 |
# ─── ARITHMETIC IN ACTION ───────────────────────────────
a, b = 17, 5
print(f"a + b = {a + b}") # 22
print(f"a - b = {a - b}") # 12
print(f"a * b = {a * b}") # 85
print(f"a / b = {a / b}") # 3.4 (float)
print(f"a // b = {a // b}") # 3 (floor)
print(f"a %% b = {a % b}") # 2 (remainder)
print(f"a ** b = {a ** b}") # 1419857 (17^5)
# ─── ARITHMETIC ON STRINGS AND LISTS ────────────────────
print("Ha" * 3) # HaHaHa
print("Hello, " + "World!") # Hello, World!
print([1, 2] + [3, 4]) # [1, 2, 3, 4]
print([0] * 5) # [0, 0, 0, 0, 0]
# ─── MODULO: MOST USEFUL "HIDDEN" OPERATOR ──────────────
# Check if a number is even or odd
print(14 % 2 == 0) # True (even)
print(15 % 2 == 0) # False (odd)
# Convert 150 minutes to hours and minutes
total_min = 150
hours = total_min // 60 # 2
minutes = total_min % 60 # 30
print(f"{hours}h {minutes}min") # 2h 30min
The % operator looks trivial but appears in almost every real program: checking odd/even, wrapping around clock values (23:00 + 3 hours → (23+3) % 24 = 2), rotating array indices, distributing work evenly across servers, and generating cyclic patterns. Learn it well.
Comparison Operators — Asking Questions
Comparison operators compare two values and always return a boolean — True or False. They are the foundation of every if statement, every while loop, and every filter in your code.
| Operator | Name | Example | Result |
|---|---|---|---|
| == | Equal to | 5 == 5 | True |
| != | Not equal to | 5 != 3 | True |
| > | Greater than | 7 > 4 | True |
| < | Less than | 3 < 8 | True |
| >= | Greater than or equal | 5 >= 5 | True |
| <= | Less than or equal | 4 <= 3 | False |
# ─── BASIC COMPARISONS ──────────────────────────────────
print(10 == 10) # True
print(10 == "10") # False (int vs str)
print(10 != 7) # True
print("apple" < "banana") # True (alphabetical order)
print("Apple" < "apple") # True (uppercase comes first)
# ─── CHAINED COMPARISONS (Python superpower!) ───────────
age = 25
# Instead of this (works but ugly):
print(age >= 18 and age <= 65) # True
# Write this (clean and mathematical):
print(18 <= age <= 65) # True
# Chain even further
x = 50
print(0 < x < 100 < 1000) # True
# ─── USING COMPARISONS IN LOGIC ─────────────────────────
score = 85
if score >= 90:
grade = "A"
elif score >= 80:
grade = "B"
elif score >= 70:
grade = "C"
else:
grade = "F"
print(f"Score {score} → Grade {grade}")
= is assignment (put a value into a variable). == is comparison (check if two values are equal). Writing if x = 5: is a SyntaxError — Python protects you. But if x == 5: is what you meant. Remember: double equals asks a question, single equals gives an answer.
Logical Operators — Combining Conditions
Logical operators combine boolean values into more complex conditions. Python uses English words — and, or, not — instead of the cryptic symbols (&&, ||, !) used by C, Java, and JavaScript.
Truth Tables
| A | B | A and B |
|---|---|---|
| True | True | True |
| True | False | False |
| False | True | False |
| False | False | False |
| A | B | A or B |
|---|---|---|
| True | True | True |
| True | False | True |
| False | True | True |
| False | False | False |
# ─── LOGICAL OPERATORS IN ACTION ────────────────────────
age = 25
has_license = True
has_car = False
# and — all conditions must be True
can_drive = age >= 18 and has_license
print(f"Can drive: {can_drive}") # True
# or — at least one condition must be True
needs_transport = not has_car or age < 16
print(f"Needs transport: {needs_transport}") # True
# not — inverts the value
is_minor = not (age >= 18)
print(f"Is minor: {is_minor}") # False
# ─── COMBINING ALL THREE ────────────────────────────────
username = "alice"
password = "secret123"
is_locked = False
can_login = (username == "alice" and
password == "secret123" and
not is_locked)
print(f"Can login: {can_login}") # True
# ─── SHORT-CIRCUIT EVALUATION ───────────────────────────
# Python stops as soon as it knows the answer
x = 0
# This is SAFE — the division never runs because x == 0 is True first
if x == 0 or (10 / x) > 1:
print("Safe division — no crash")
Assignment Operators — Store and Update
The basic assignment is = — it stores a value into a variable. Python also provides compound assignment operators that combine an arithmetic operation with assignment. They save typing and make code cleaner.
| Operator | Example | Equivalent To | Meaning |
|---|---|---|---|
| = | x = 5 | — | Store 5 in x |
| += | x += 3 | x = x + 3 | Add and reassign |
| -= | x -= 3 | x = x - 3 | Subtract and reassign |
| *= | x *= 3 | x = x * 3 | Multiply and reassign |
| /= | x /= 3 | x = x / 3 | Divide and reassign |
| //= | x //= 3 | x = x // 3 | Floor divide and reassign |
| %= | x %= 3 | x = x % 3 | Modulo and reassign |
| **= | x **= 3 | x = x ** 3 | Power and reassign |
| := | (n := 10) | Walrus operator | Assign inside an expression (Python 3.8+) |
# ─── COMPOUND ASSIGNMENT IN A COUNTER ──────────────────
score = 0
score += 10 # same as: score = score + 10 → 10
score += 25 # → 35
score -= 5 # → 30
score *= 2 # → 60
score //= 3 # → 20
print(f"Final score: {score}")
# ─── COMPOUND ASSIGNMENT ON STRINGS ─────────────────────
message = "Hello"
message += ", " # append
message += "World!"
print(message) # Hello, World!
# ─── COMPOUND ASSIGNMENT ON LISTS ───────────────────────
tasks = ["wake up"]
tasks += ["eat", "code"] # extend the list
tasks *= 2 # duplicate the list
print(tasks)
# ─── WALRUS OPERATOR := (Python 3.8+) ───────────────────
# Assign a value AND use it in the same expression
numbers = [3, 7, 15, 22, 31]
if (n := len(numbers)) > 3:
print(f"List has {n} items — that's plenty")
Bitwise Operators — Working with Binary
Bitwise operators work directly on the binary representation of integers. Every integer inside your computer is stored as a sequence of bits (0s and 1s). Bitwise operators manipulate those bits directly. You will rarely need them in day-to-day code, but they are essential in networking, cryptography, permissions, and hardware programming.
| Operator | Name | Example | Binary | Result |
|---|---|---|---|---|
| & | AND | 12 & 10 | 1100 & 1010 | 8 (1000) |
| | | OR | 12 | 10 | 1100 | 1010 | 14 (1110) |
| ^ | XOR | 12 ^ 10 | 1100 ^ 1010 | 6 (0110) |
| ~ | NOT (invert) | ~12 | ~1100 | -13 |
| << | Left shift | 3 << 2 | 11 → 1100 | 12 |
| >> | Right shift | 12 >> 2 | 1100 → 11 | 3 |
# ─── BITWISE OPERATIONS ─────────────────────────────────
a = 12 # 1100 in binary
b = 10 # 1010 in binary
print(f"a & b = {a & b}") # 8 (1000) bit is 1 only if BOTH are 1
print(f"a | b = {a | b}") # 14 (1110) bit is 1 if EITHER is 1
print(f"a ^ b = {a ^ b}") # 6 (0110) bit is 1 only if DIFFERENT
print(f"~a = {~a}") # -13 inverts all bits
# ─── SHIFTS ARE MULTIPLICATION/DIVISION BY POWERS OF 2 ──
print(5 << 1) # 10 (5 * 2)
print(5 << 3) # 40 (5 * 8)
print(40 >> 2) # 10 (40 / 4)
# ─── VIEW BINARY REPRESENTATION ─────────────────────────
print(bin(12)) # 0b1100
print(bin(10)) # 0b1010
print(bin(12 & 10)) # 0b1000
Real-world uses: permission flags (Unix file permissions use bitwise ops), network programming (IP address subnetting), compression algorithms, emoji/unicode handling, and competitive programming (fast math tricks). For everyday app development, you'll rarely touch bitwise operators — but knowing they exist matters.
Membership Operators — Does It Contain This?
Membership operators in and not in check whether a value exists inside a collection (list, tuple, string, set, dictionary). They return a boolean and are one of the most-used features in Python.
# ─── MEMBERSHIP IN LISTS ────────────────────────────────
fruits = ["apple", "banana", "cherry"]
print("apple" in fruits) # True
print("mango" in fruits) # False
print("mango" not in fruits) # True
# ─── MEMBERSHIP IN STRINGS (checks substrings) ──────────
sentence = "Python is awesome"
print("Python" in sentence) # True
print("python" in sentence) # False (case-sensitive!)
print("awe" in sentence) # True (substring match)
# ─── MEMBERSHIP IN DICTIONARIES (checks KEYS, not values) ──
user = {"name": "Alice", "age": 30, "role": "admin"}
print("name" in user) # True (key exists)
print("Alice" in user) # False (Alice is a VALUE, not a key)
print("Alice" in user.values()) # True (check values explicitly)
# ─── PRACTICAL USE ──────────────────────────────────────
valid_roles = ["admin", "editor", "viewer"]
current_role = input("Enter your role: ")
if current_role in valid_roles:
print(f"Access granted as {current_role}")
else:
print("Invalid role")
Identity Operators — Same Object or Just Equal?
Identity operators check whether two variables point to the exact same object in memory — not just whether their values are equal. This is a subtle but critical distinction.
| Checks | Meaning |
|---|---|
| Value equality | Do they hold the same value? |
| Uses __eq__ | Compares content |
| Fast for primitives | Slower for large objects |
| Checks | Meaning |
|---|---|
| Object identity | Are they the same object in memory? |
| Uses id() | Compares memory address |
| Always fast | Constant time |
# ─── == vs is ───────────────────────────────────────────
a = [1, 2, 3]
b = [1, 2, 3] # same values, but a DIFFERENT list
c = a # c and a point to the SAME list
print(a == b) # True — same contents
print(a is b) # False — different objects
print(a is c) # True — same object
print(id(a), id(b), id(c)) # a and c share the same id
# ─── THE ONE PLACE TO ALWAYS USE 'is' ───────────────────
# Checking against None, True, or False — always use 'is'
value = None
if value is None: # ✓ Pythonic and correct
print("No value provided")
# NOT this (works but discouraged):
# if value == None:
# ─── SUBTLE GOTCHA — SMALL INTEGER CACHING ──────────────
x = 256
y = 256
print(x is y) # True (Python caches small ints -5 to 256)
x = 257
y = 257
print(x is y) # May be False — outside cache range!
# Lesson: NEVER use 'is' to compare numbers or strings.
# Use 'is' ONLY for None, True, False.
Use is only when comparing to None, True, or False. For everything else (numbers, strings, lists, dicts), use ==. Getting this wrong causes subtle, hard-to-find bugs that pass all your tests and then fail in production.
Operator Precedence — Who Goes First?
Python follows the exact same rule. Every operator has a precedence rank. When multiple operators appear in one expression, Python evaluates the highest-precedence ones first. If two operators have the same precedence, Python uses associativity (usually left-to-right) to decide.
Get this wrong and your calculation returns a wildly incorrect answer with no error message. Nothing crashes — you just get the wrong result. This is why parentheses are your friend.
The Complete Precedence Table (High to Low)
| Rank | Operator | Category | Associativity |
|---|---|---|---|
| 1 (highest) | () | Parentheses — force priority | N/A |
| 2 | ** | Exponentiation | Right-to-left |
| 3 | +x -x ~x | Unary plus, minus, bitwise NOT | Right-to-left |
| 4 | * / // % | Multiplication, division, modulo | Left-to-right |
| 5 | + - | Addition, subtraction | Left-to-right |
| 6 | << >> | Bitwise shifts | Left-to-right |
| 7 | & | Bitwise AND | Left-to-right |
| 8 | ^ | Bitwise XOR | Left-to-right |
| 9 | | | Bitwise OR | Left-to-right |
| 10 | == != > < >= <= is is not in not in | Comparisons, identity, membership | Left-to-right |
| 11 | not | Logical NOT | Right-to-left |
| 12 | and | Logical AND | Left-to-right |
| 13 (lowest) | or | Logical OR | Left-to-right |
Precedence in Action — Trace These Examples
# ─── EXAMPLE 1: Basic arithmetic order ──────────────────
result = 2 + 3 * 4
# Step 1: 3 * 4 = 12 (multiplication has higher precedence)
# Step 2: 2 + 12 = 14
print(result) # 14
# ─── EXAMPLE 2: Parentheses override precedence ─────────
result = (2 + 3) * 4
# Step 1: 2 + 3 = 5 (parens win)
# Step 2: 5 * 4 = 20
print(result) # 20
# ─── EXAMPLE 3: Exponent is right-associative ───────────
result = 2 ** 3 ** 2
# NOT (2 ** 3) ** 2 = 64
# Correct: 2 ** (3 ** 2) = 2 ** 9 = 512
print(result) # 512
# ─── EXAMPLE 4: Unary minus vs exponent ─────────────────
result = -2 ** 2
# ** has higher precedence than unary -
# = -(2 ** 2) = -4 NOT (-2) ** 2 = 4
print(result) # -4
# ─── EXAMPLE 5: Mixing comparison and logical ───────────
x = 10
result = x > 5 and x < 20 or x == 100
# Comparisons first: True and True or False
# and before or: (True and True) or False
# = True or False = True
print(result) # True
# ─── EXAMPLE 6: The classic trap ────────────────────────
avg = 10 + 20 + 30 / 3
# / happens FIRST → 30 / 3 = 10
# Then 10 + 20 + 10 = 40 (NOT 20 as you might think!)
print(avg) # 40.0
# The correct way:
avg = (10 + 20 + 30) / 3
print(avg) # 20.0
When in doubt, use parentheses. Nobody has ever been fired for adding extra parentheses. They cost zero performance, make your intent crystal clear, and eliminate every precedence bug. Write (a * b) + c instead of trusting your memory of the precedence table. Your future self reading the code at 2 AM will thank you.
Common Operator Traps & Pitfalls
if x == 5: # Correct
10 // 3 = 3 (int)
(-2) ** 2 = 4
if x == 100: # correct
1 and "hi" → "hi"
math.isclose(a, b)
# ─── AND/OR RETURN THE ACTUAL VALUE, NOT True/False ─────
# This surprises many beginners
print(5 and 10) # 10 (both truthy → returns last)
print(0 and 10) # 0 (short-circuits at 0)
print(5 or 10) # 5 (first truthy value)
print(0 or 10) # 10 (0 is falsy, so returns 10)
print("" or "default") # "default" (useful pattern!)
# PATTERN: default values with or
name = ""
display = name or "Anonymous"
print(display) # Anonymous
# ─── FLOAT EQUALITY TRAP ────────────────────────────────
print(0.1 + 0.2 == 0.3) # False !!!
# The correct way:
import math
print(math.isclose(0.1 + 0.2, 0.3)) # True
Complete Practice Program — Operators Sandbox
This program uses every category of operator in a single working script. Type it out, run it, and modify values to see how the results change.
# operators_sandbox.py — All Python operators in one place
def main():
# ─── ARITHMETIC ─────────────────────────────────────
price = 99.99
quantity = 3
tax_rate = 0.15
subtotal = price * quantity
tax = subtotal * tax_rate
total = subtotal + tax
print("=== ORDER SUMMARY ===")
print(f"Subtotal: ${subtotal:.2f}")
print(f"Tax: ${tax:.2f}")
print(f"Total: ${total:.2f}")
# ─── ASSIGNMENT (compound) ──────────────────────────
balance = 500.00
balance -= total # subtract purchase
balance += 50.00 # add refund
print(f"Balance: ${balance:.2f}")
# ─── COMPARISON & LOGICAL ───────────────────────────
is_vip = True
order_size = quantity
qualifies_for_discount = (
(order_size >= 3 or is_vip) and
balance > 0 and
not (total > 1000)
)
print(f"Discount: {qualifies_for_discount}")
# ─── MEMBERSHIP ─────────────────────────────────────
payment_methods = ["card", "paypal", "cash"]
chosen = "card"
if chosen in payment_methods:
print(f"Paying via: {chosen}")
else:
print("Unsupported payment method")
# ─── IDENTITY ──────────────────────────────────────
error = None
if error is None:
print("Order processed successfully")
# ─── PRECEDENCE DEMO ────────────────────────────────
# Without parens: * happens before +
a = 2 + 3 * 4 # = 14
# With parens: + happens first
b = (2 + 3) * 4 # = 20
# Exponent is right-associative
c = 2 ** 3 ** 2 # = 512, not 64
print(f"Precedence: {a}, {b}, {c}")
# ─── BITWISE (flag system) ──────────────────────────
READ = 0b100 # 4
WRITE = 0b010 # 2
EXECUTE = 0b001 # 1
permissions = READ | WRITE # combine flags → 6
print(f"Can read? {bool(permissions & READ)}")
print(f"Can write? {bool(permissions & WRITE)}")
print(f"Can execute? {bool(permissions & EXECUTE)}")
if __name__ == "__main__":
main()
Exercises — Test Your Understanding
Try each exercise on paper first — predict the output before running the code. This is how you truly learn operators. Answers follow at the end of each exercise.
# Solution to Exercise 2
n = int(input("Enter a number: "))
if n % 2 == 0:
print(f"{n} is even")
else:
print(f"{n} is odd")
# Bonus — FizzBuzz-style
if n % 15 == 0:
print(f"{n} is divisible by both 3 and 5")
elif n % 3 == 0:
print(f"{n} is divisible by 3")
elif n % 5 == 0:
print(f"{n} is divisible by 5")
# Solution to Exercise 4
a = float(input("First number: "))
op = input("Operator (+ - * / // %% **): ")
b = float(input("Second number: "))
valid_ops = ["+", "-", "*", "/", "//", "%", "**"]
if op not in valid_ops:
print("Invalid operator!")
elif op in ["/", "//", "%"] and b == 0:
print("Cannot divide by zero!")
else:
if op == "+": result = a + b
elif op == "-": result = a - b
elif op == "*": result = a * b
elif op == "/": result = a / b
elif op == "//": result = a // b
elif op == "%": result = a % b
elif op == "**": result = a ** b
print(f"{a} {op} {b} = {result}")
# Solution to Exercise 5
password = input("Enter password: ")
is_strong = (
len(password) >= 8 and
any(c.isdigit() for c in password) and
any(c.isupper() for c in password) and
any(c.islower() for c in password)
)
if is_strong:
print("Strong password ✓")
else:
print("Weak password — must have 8+ chars, digit, upper, lower")
# Solution to Exercise 6
year = int(input("Enter a year: "))
is_leap = (year % 4 == 0 and year % 100 != 0) or year % 400 == 0
if is_leap:
print(f"{year} is a leap year")
else:
print(f"{year} is not a leap year")