Operators and Expressions

Reviewed & published by Brayan K

Learn how to perform calculations, compare values, and combine conditions using Python's operators.

Part of the free Python course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.

What You'll Learn

1 What Are Operators?

Operators are special symbols that tell Python to perform specific operations on values. Think of them as action words that do something with your data.

Here, + is the operator, and 10 and 5 are the operands (the values being operated on).

Python has several types of operators. We'll cover them in order of how often you'll use them.

2 Arithmetic Operators (Math)

These are the operators you'll use most often. They perform mathematical calculations.

OperatorNameExampleResultWhen to Use
+Addition10 + 313Add numbers together
-Subtraction10 - 37Find differences
*Multiplication10 * 330Multiply values
/Division10 / 33.333...Divide (returns decimal)
//Floor Division10 // 33Divide (whole number only)
%Modulus10 % 31Get remainder after division
**Exponent2 ** 38Raise to a power (2³)
# Arithmetic Operators in Python
a = 10
b = 3

print("Addition:", a + b)        # 13
print("Subtraction:", a - b)     # 7
print("Multiplication:", a * b)  # 30
print("Division:", a / b)        # 3.333...
print("Floor Division:", a // b) # 3
print("Modulus:", a % b)         # 1
print("Exponent:", a ** b)       # 1000

# Practical example: Is a number even or odd?
number = 17
remainder = number % 2
print(f"{number} divided by 2 has remainder: {remainder}")
if remainder == 0:
    print("Even number!")
else:
    print("Odd number!")

# ✅ Expected output:
# Addition: 13
# Subtraction: 7
# Multiplication: 30
# Division: 3.3333333333333335
# Floor Division: 3
# Modulus: 1
# Exponent: 1000
# 17 divided by 2 has remainder: 1
# Odd number!

↗ Arithmetic in Real Programs

Arithmetic operators aren't just for textbook maths — they solve real problems constantly. Here are the patterns you'll reach for again and again.

Modulo (%) — the most underrated operator

# Pattern 1: Even or odd check
print(7 % 2)    # 1 → odd
print(8 % 2)    # 0 → even

# Pattern 2: Wrapping numbers (e.g. clock arithmetic)
hour = 14
print(hour % 12)    # 2 → "2 o'clock" in 12-hour format

# Pattern 3: Every Nth item (e.g. every 5th row gets highlighted)
for i in range(1, 11):
    if i % 5 == 0:
        print(f"Row {i} gets highlighted!")

Modulo is used constantly: pagination, cyclical patterns, divisibility checks, time conversion. Once you recognise it, you'll see it everywhere.

Floor Division (//) — whole-number results

# Convert seconds to minutes and seconds
total_seconds = 275
minutes = total_seconds // 60    # 4
seconds = total_seconds % 60     # 35
print(f"{minutes}m {seconds}s")  # "4m 35s"

# Pagination: which page is item 47 on? (10 items per page)
item_index = 47
items_per_page = 10
page_number = (item_index // items_per_page) + 1
print(f"Item 47 is on page {page_number}")  # Page 5

// and % are a natural pair — they give you the quotient and the remainder from the same division.

Exponent (**) — real-world uses

# Area of a square
side = 7
area = side ** 2
print(f"Area: {area} sq units")  # 49

# Compound interest: A = P * (1 + r) ** n
principal  = 1000
rate       = 0.05    # 5%
years      = 10
amount     = principal * (1 + rate) ** years
print(f"After {years} years: £{amount:.2f}")  # £1628.89

# Kilobytes to bytes
kb = 64
bytes_ = kb * 2 ** 10
print(f"{kb}KB = {bytes_} bytes")  # 65536 bytes

3 Comparison Operators

Comparison operators compare two values and return True or False. You'll use these constantly with if statements.

OperatorMeaningExampleResult
==Equal to5 == 5True
!=Not equal to5 != 3True
>Greater than5 > 3True
<Less than5 < 3False
>=Greater than or equal5 >= 5True
<=Less than or equal5 <= 3False

= is for assignment (storing a value)

== is for comparison (checking if equal)

# Comparison Operators
a = 10
b = 5

print("a == b:", a == b)   # False (10 is not equal to 5)
print("a != b:", a != b)   # True (10 is not equal to 5)
print("a > b:", a > b)     # True (10 is greater than 5)
print("a < b:", a < b)     # False (10 is not less than 5)
print("a >= b:", a >= b)   # True (10 is greater than or equal to 5)
print("a <= b:", a <= b)   # False (10 is not less than or equal to 5)

# Common use: checking conditions
age = 18
print("Can vote?", age >= 18)  # True

# Works with strings too!
print("'apple' < 'banana':", "apple" < "banana")  # True (alphabetical)

# ✅ Expected output:
# a == b: False
# a != b: True
# a > b: True
# a < b: False
# a >= b: True
# a <= b: False
# Can vote? True
# 'apple' < 'banana': True

↗ Comparing Strings and Chaining Comparisons

Comparison operators aren't just for numbers. Understanding how they work with strings — and how to chain them — makes your code far more expressive.

Strings compare alphabetically (lexicographically)

print("apple" < "banana")   # True  — 'a' comes before 'b'
print("zebra" > "ant")      # True  — 'z' comes after 'a'
print("Apple" < "apple")    # True  — uppercase letters come first in Python!

# Equality check is case-sensitive
name = "Alice"
print(name == "alice")   # False — different case
print(name == "Alice")   # True

Python compares strings character by character using their Unicode value. Capital letters (A–Z) have lower values than lowercase (a–z), so "Apple" < "apple" is True. This matters for sorting names or usernames.

Chained comparisons — Python's elegant shortcut

Most languages require you to write two separate conditions. Python lets you chain them like a maths expression:

age >= 13 and age <= 17
13 <= age <= 17
score = 75

# Check if score is in a grade band
print(90 <= score <= 100)  # False — not an A
print(70 <= score <= 89)   # True  — it's a B
print(0  <= score <= 100)  # True  — valid score range

# Very readable real-world use
temperature = 22
is_comfortable = 18 <= temperature <= 26
print(f"Comfortable temperature? {is_comfortable}")  # True

⚠️ Never compare different types with < or >

# This works (== is fine across types)
print(1 == "1")   # False — different types, no error

# These crash with TypeError:
print(1 < "1")    # ❌ TypeError: '<' not supported between str and int
print(5 > "3")    # ❌ TypeError

Equality (==) across types is allowed and simply returns False. But ordering comparisons (<, >) between incompatible types crash your program. This usually happens when input() returns a string and you forget to convert it with int().

4 Logical Operators

Logical operators let you combine multiple conditions. They're essential for complex decision-making.

Both conditions must be True

At least one must be True

A theme park ride might require: age >= 12 and height >= 140 Both conditions must be true to ride!

# Logical Operators
age = 25
has_license = True
has_car = False

# and - both must be true
can_drive = age >= 18 and has_license
print("Can drive?", can_drive)  # True

# or - at least one must be true
can_travel = has_car or has_license
print("Can travel?", can_travel)  # True (has license)

# not - reverses the value
is_minor = not (age >= 18)
print("Is minor?", is_minor)  # False

# Combining them
print("---")
print("Complex example:")
is_weekend = True
is_sunny = True
has_free_time = True

go_to_park = is_weekend and is_sunny and has_free_time
print("Go to park?", go_to_park)  # True

# ✅ Expected output:
# Can drive? True
# Can travel? True
# Is minor? False
# ---
# Complex example:
# Go to park? True

↗ Logical Operators: Truth Tables and Short-Circuit Evaluation

To use logical operators with confidence, you need to know every possible outcome — and understand a powerful performance trick Python uses called short-circuit evaluation.

Truth tables — every possible combination

ABA and B
TrueTrueTrue
TrueFalseFalse
FalseTrueFalse
FalseFalseFalse
ABA or B
TrueTrueTrue
TrueFalseTrue
FalseTrueTrue
FalseFalseFalse
Anot A
TrueFalse
FalseTrue

Summary: and needs ALL conditions True. or needs ANY condition True. not flips the result.

Short-circuit evaluation — Python stops early

Python is lazy in a clever way: it stops evaluating as soon as the result is certain.

# With 'and': if the first part is False, Python skips the second
# (False and ANYTHING is always False)
x = 0
result = x != 0 and (10 / x) > 1   # Safe! Division never runs
print(result)  # False

# With 'or': if the first part is True, Python skips the second
# (True or ANYTHING is always True)
name = "Alice"
result = name != "" or some_expensive_function()  # Second part skipped
print(result)  # True

This isn't just trivia — it's a common technique to prevent crashes. Check that a value is safe before using it, using and.

Combining and / or / not — operator priority

When mixing logical operators, priority order is: not → and → or. Use parentheses to be explicit:

age = 20
has_ticket = True
is_vip = False

# Without parentheses — can be confusing:
result = age >= 18 and has_ticket or is_vip

# With parentheses — crystal clear intent:
result = (age >= 18 and has_ticket) or is_vip
print(result)  # True

# 'not' flips an entire condition:
is_banned = False
can_enter = has_ticket and not is_banned
print(can_enter)  # True

5 Assignment Operators

Assignment operators are shortcuts for updating a variable's value. They combine an operation with assignment.

ShortcutSame AsExample (x = 10)Result
+=x = x + nx += 515
-=x = x - nx -= 37
*=x = x * nx *= 220
/=x = x / nx /= 25.0
//=x = x // nx //= 33
%=x = x % nx %= 31
**=x = x ** nx **= 2100
# Assignment Operators - Shortcuts!
score = 100

# Instead of: score = score + 10
score += 10
print("After += 10:", score)  # 110

score -= 20
print("After -= 20:", score)  # 90

score *= 2
print("After *= 2:", score)   # 180

score //= 3
print("After //= 3:", score)  # 60

# Common use: counting
count = 0
count += 1  # increment
count += 1
count += 1
print("Count:", count)  # 3

# ✅ Expected output:
# After += 10: 110
# After -= 20: 90
# After *= 2: 180
# After //= 3: 60
# Count: 3

↗ Augmented Assignment: Real Patterns You'll Use Every Day

The shorthand operators aren't just about typing less — they represent three fundamental programming patterns that appear in virtually every program ever written.

Pattern 1: The Counter

Incrementing a number by 1 each time something happens is called a counter. It's one of the most common patterns in programming:

login_attempts = 0
errors = 0
words_typed = 0

# Each time something happens:
login_attempts += 1   # user tried to log in
errors += 1           # an error occurred
words_typed += 1      # user typed a word

print(f"Login attempts: {login_attempts}")
print(f"Errors: {errors}")

# Decrement works too:
lives = 3
lives -= 1   # player lost a life
print(f"Lives remaining: {lives}")

Pattern 2: The Accumulator

Adding values to a running total is called an accumulator. This is how shopping carts, bank balances, and totals work:

# Shopping cart total
cart_total = 0.0

cart_total += 29.99   # Added Python Book
cart_total += 9.99    # Added USB Cable
cart_total += 14.50   # Added Notebook

print(f"Cart total: £{cart_total:.2f}")  # £54.48

# Apply discount
discount_percent = 10
cart_total *= (1 - discount_percent / 100)
print(f"After {discount_percent}% off: £{cart_total:.2f}")  # £49.03

Pattern 3: String Building

+= works on strings too — it appends text to an existing string:

# Building a message piece by piece
message = "Hello"
message += ", "
message += "welcome to "
message += "Python!"
print(message)   # "Hello, welcome to Python!"

# Practical: building a CSV row
row = ""
row += "Alice"
row += ","
row += "25"
row += ","
row += "London"
print(row)   # "Alice,25,London"

In large programs, f-strings are usually better for complex string construction — but += is handy when you're building a string incrementally over time.

6 Operator Precedence (Order of Operations)

Just like in math, Python follows a specific order when evaluating expressions with multiple operators. Remember PEMDAS!

PEMDAS - Order of Operations

From highest to lowest priority

Pro Tip: When in Doubt, Use Parentheses!

Parentheses make your code clearer and ensure operations happen in the order you expect. (2 + 3) * 4 is clearer than 2 + 3 * 4

# Operator Precedence - Order Matters!

# Without parentheses
result1 = 2 + 3 * 4
print("2 + 3 * 4 =", result1)  # 14 (multiply first)

# With parentheses
result2 = (2 + 3) * 4
print("(2 + 3) * 4 =", result2)  # 20 (addition first)

# Exponents come before multiply
result3 = 2 * 3 ** 2
print("2 * 3 ** 2 =", result3)  # 18 (3² = 9, then 2 * 9)

# Complex expression
result4 = (10 + 5) * 2 - 3 ** 2
print("(10 + 5) * 2 - 3 ** 2 =", result4)  # 21
# Steps: (15) * 2 - 9 = 30 - 9 = 21

# ✅ Expected output:
# 2 + 3 * 4 = 14
# (2 + 3) * 4 = 20
# 2 * 3 ** 2 = 18
# (10 + 5) * 2 - 3 ** 2 = 21

↗ Building Complex Expressions and the Ternary Operator

Operators become most powerful when combined. Here's how to read and write complex expressions confidently — plus a cleaner way to write simple if/else logic.

Reading complex expressions step by step

When you see a long expression, break it down by precedence:

# What does this evaluate to?
result = 2 + 3 ** 2 * 4 - 1

# Step 1: Exponents first   → 3 ** 2 = 9
# Step 2: Multiplication    → 9 * 4  = 36
# Step 3: Left to right add/sub → 2 + 36 - 1 = 37
print(result)  # 37

# With parentheses to match intent:
discount = 100
tax_rate = 0.20
base_price = 50
final = (base_price - discount * 0.1) * (1 + tax_rate)
# Step 1: discount * 0.1 = 10
# Step 2: base_price - 10 = 40
# Step 3: 1 + tax_rate = 1.20
# Step 4: 40 * 1.20 = 48.0
print(f"Final price: £{final:.2f}")

The ternary operator — if/else in one line

Python has a compact syntax for simple if/else decisions called a conditional expression (or ternary operator):

age = 20

# Long way (3 lines):
if age >= 18:
    status = "adult"
else:
    status = "minor"

# Ternary (1 line — identical result):
status = "adult" if age >= 18 else "minor"
print(status)   # adult

# More examples:
score = 72
grade   = "Pass" if score >= 60 else "Fail"
label   = "even" if score % 2 == 0 else "odd"
display = f"Score: {score} ({grade}, {label})"
print(display)

7 Identity and Membership Operators

These operators check relationships between objects and values.

Identity Operators

Check if two variables refer to the same object

Membership Operators

Check if a value exists in a sequence

# Identity Operators (is, is not)
a = [1, 2, 3]
b = [1, 2, 3]
c = a

print("a == b:", a == b)   # True (same values)
print("a is b:", a is b)   # False (different objects)
print("a is c:", a is c)   # True (same object)

# Membership Operators (in, not in)
fruits = ["apple", "banana", "cherry"]
print("---")
print("'banana' in fruits:", "banana" in fruits)      # True
print("'grape' in fruits:", "grape" in fruits)        # False
print("'grape' not in fruits:", "grape" not in fruits) # True

# Works with strings too!
message = "Hello, World!"
print("---")
print("'World' in message:", "World" in message)  # True
print("'Python' in message:", "Python" in message)  # False

# ✅ Expected output:
# a == b: True
# a is b: False
# a is c: True
# ---
# 'banana' in fruits: True
# 'grape' in fruits: False
# 'grape' not in fruits: True
# ---
# 'World' in message: True
# 'Python' in message: False
# 🎯 YOUR TURN — replace each ___ using the hint beside it.

cartons = 17
per_box = 5

# 1) Whole boxes only. A single / would give you 3.4 here.
full_boxes = cartons ___ per_box       # 👉 replace ___ with //

# 2) What is left over after filling those boxes.
left_over = cartons ___ per_box        # 👉 replace ___ with %

print("Full boxes:", full_boxes)
print("Left over: ", left_over)

exact = cartons / per_box
print("Exact:     ", exact)

# 3) Two to the power of ten.
print("Power:", 2 ___ 10)              # 👉 replace ___ with **

needs_extra = left_over > 0

# 4) BOTH have to be true. Python spells it as a word.
fits_on_pallet = full_boxes <= 3 ___ left_over < 4   # 👉 replace ___ with and

print("Needs an extra box?", needs_extra)
print("Fits on one pallet?", fits_on_pallet)

shipped = 0
# 5) Add to shipped in one step.
shipped ___ full_boxes                 # 👉 replace ___ with +=
shipped += 1                           # the part-full box goes too
print("Boxes shipped:", shipped)

# Python lets you chain comparisons the way maths does.
print("Chained:", 0 < left_over < 5)

# ✅ Expected output:
# Full boxes: 3
# Left over:  2
# Exact:      3.4
# Power: 1024
# Needs an extra box? True
# Fits on one pallet? True
# Boxes shipped: 4
# Chained: True

↗ Membership Operators: Practical Patterns

in and not in are more versatile than they first appear. Here's how they're used in real code.

Searching inside strings

email = "[email protected]"

# Check it has an @ sign and a dot
has_at   = "@" in email
has_dot  = "." in email
looks_valid = has_at and has_dot
print(f"Looks like a valid email: {looks_valid}")  # True

# Check for forbidden words
comment = "This is a great tutorial!"
banned_words = ["spam", "scam", "hack"]
is_clean = not any(word in comment for word in banned_words)
print(f"Comment is clean: {is_clean}")  # True

Validating against a list of allowed values

# Input validation — only allow specific options
valid_sizes   = ["small", "medium", "large"]
valid_colours = ["red", "green", "blue", "black", "white"]

chosen_size   = "medium"
chosen_colour = "purple"

if chosen_size not in valid_sizes:
    print(f"Invalid size: {chosen_size}")

if chosen_colour not in valid_colours:
    print(f"Sorry, we don't stock {chosen_colour}")
# Output: "Sorry, we don't stock purple"

# Days of the week check
weekdays = ["Monday","Tuesday","Wednesday","Thursday","Friday"]
weekend  = ["Saturday","Sunday"]
today    = "Saturday"

is_workday = today in weekdays
print(f"Is {today} a work day? {is_workday}")  # False

This pattern is everywhere: checking file extensions, validating user choices, filtering allowed commands, verifying roles and permissions.

! Common Operator Mistakes (And How to Fix Them)

These mistakes catch nearly every beginner at least once. Recognise them now and you'll debug much faster.

1. Using = instead of == in a condition

# ❌ This assigns 5 to x inside a condition (causes SyntaxError in Python)
if x = 5:
    print("five")

# ✅ Correct — use double equals to compare
if x == 5:
    print("five")

Python actually prevents this in conditions and raises a SyntaxError. In some other languages it silently does the wrong thing — Python protects you here.

2. Division by zero

# ❌ This crashes with ZeroDivisionError
result = 10 / 0

# ✅ Check first, then divide
divisor = 0
if divisor != 0:
    result = 10 / divisor
else:
    print("Can't divide by zero!")

3. True and False are equal to 1 and 0

print(True == 1)   # True  — surprising!
print(False == 0)  # True
print(True + True) # 2    — Python lets you do math with booleans

# This causes bugs when you expect a boolean but get an int:
score = 5
is_high = score > 3    # True
print(is_high + 10)    # 11 — works but looks very wrong

Technically valid Python, but treat booleans as booleans and numbers as numbers. Don't mix them intentionally.

4. Comparing floats with ==

# ❌ This can fail due to floating point precision
total = 0.1 + 0.2
print(total == 0.3)   # False! (total is 0.30000000000000004)

# ✅ Round first, then compare — or use a tolerance
print(round(total, 2) == 0.3)           # True
print(abs(total - 0.3) < 0.0001)        # True (within tolerance)

Always use round() or a tolerance when comparing floats for equality. This trips up developers at every level.

★ Mini-Project: Password Strength Checker

Let's combine every operator type from this lesson into one real program. This is exactly the kind of validation logic used in real login systems.

Operators used in this project

# Password Strength Checker
password = "MyP@ssw0rd"

# Define requirements using constants
MIN_LENGTH    = 8
SPECIAL_CHARS = "!@#$%^&*"
DIGITS        = "0123456789"

# Check each requirement (comparison + membership operators)
is_long_enough   = len(password) >= MIN_LENGTH
has_uppercase    = any(c.isupper() for c in password)
has_lowercase    = any(c.islower() for c in password)
has_digit        = any(c in DIGITS for c in password)
has_special      = any(c in SPECIAL_CHARS for c in password)

# Count how many requirements are met (augmented assignment + arithmetic)
strength_score = 0
strength_score += 1 if is_long_enough else 0
strength_score += 1 if has_uppercase  else 0
strength_score += 1 if has_lowercase  else 0
strength_score += 1 if has_digit      else 0
strength_score += 1 if has_special    else 0

# Determine strength label (ternary + comparison)
if strength_score == 5:
    strength = "Strong ✓"
elif strength_score >= 3:
    strength = "Medium"
else:
    strength = "Weak ✗"

# Build the report (f-strings + logical operators)
print(f"Password: {'*' * len(password)}")
print(f"Length:       {'✓' if is_long_enough else '✗'} (min {MIN_LENGTH})")
print(f"Uppercase:    {'✓' if has_uppercase  else '✗'}")
print(f"Lowercase:    {'✓' if has_lowercase  else '✗'}")
print(f"Digit:        {'✓' if has_digit      else '✗'}")
print(f"Special char: {'✓' if has_special    else '✗'}")
print(f"\nStrength: {strength} ({strength_score}/5)")

Can you add a check that the password doesn't contain the word "password"? Hint: use not in. What about checking it doesn't start with a digit? Hint: use password[0] in DIGITS.

Membership

Great Job!

You've learned all the essential Python operators. These are the building blocks for writing expressions and making decisions in your programs. In the next lesson, you'll learn about control flow and how to use these operators with if statements!

Lesson done — you can now make Python calculate anything!

Arithmetic, comparison, logical, assignment, identity, and membership operators — you've got them all. These are the building blocks of every expression in every Python program.

Practice quiz

What does 10 % 3 evaluate to?

  • 3
  • 1
  • 3.33
  • 0

Answer: 1. % is modulus (remainder); 10 divided by 3 leaves remainder 1.

What is the result of 2 ** 3?

  • 6
  • 9
  • 8
  • 5

Answer: 8. ** is the exponent operator; 2 to the power of 3 is 8.

What does 2 + 3 * 4 evaluate to?

  • 20
  • 14
  • 24
  • 9

Answer: 14. By PEMDAS, multiplication happens first: 3 * 4 = 12, then 2 + 12 = 14.

Which operator checks if two values are EQUAL?

  • =
  • ==
  • !=
  • is

Answer: ==. == compares for equality; a single = assigns a value.

What does 'banana' in ['apple', 'banana', 'cherry'] return?

  • True
  • False
  • 1
  • Error

Answer: True. The membership operator 'in' returns True when the value is found.

Which logical operator requires BOTH conditions to be True?

  • or
  • not
  • and
  • in

Answer: and. 'and' is True only when both operands are True.

What does 2 * 3 ** 2 evaluate to?

  • 36
  • 18
  • 12
  • 64

Answer: 18. Exponents bind before multiplication: 3 ** 2 = 9, then 2 * 9 = 18.

What is the result of not (5 >= 10)?

  • True
  • False
  • Error
  • None

Answer: True. 5 >= 10 is False, and 'not False' is True.

Using Python's ternary: status = 'adult' if age >= 18 else 'minor'. If age is 20, status is?

  • 'minor'
  • 'adult'
  • True
  • Error

Answer: 'adult'. Since 20 >= 18 is True, the value before 'if' ('adult') is chosen.

What does the expression 1 < '1' do in Python?

  • Returns True
  • Returns False
  • Raises a TypeError
  • Returns 0

Answer: Raises a TypeError. Ordering comparisons (<, >) between an int and a str raise a TypeError.

Continue this course