Python Lesson 4: Numbers, Operators & Expressions — Arithmetic, Comparison, Logic & Precedence
Chapters: 0:00 Lesson 4: Numbers, Operators, and Expressions 0:25 The Words We Will Use 0:50 Arithmetic Operators 1:15 Two Kinds of Division 1:47 Modulo: The Remainder 2:17 Comparison Operators 2:42 Logical Operators: and, or, not 3:08 Operator Precedence 3:41 How Python Evaluates, Step by Step 4:09 Type Conversion 4:38 Common Mistakes 5:07 Float Surprises 5:41 Choosing the Right Tool 6:16 Recap Master how Python does math and makes decisions! In this lesson you'll learn arithmetic operators (+, -, *, /, //, %, **), the difference between true division and floor division, and how modulo finds remainders. We cover comparison operators, the logical operators and/or/not, and how operator precedence decides what Python evaluates first — step by step. You'll also learn type conversion between int, float, and str, why floats sometimes give surprising results, and how to choose the right numeric tool for the job. Perfect for beginners following along with the full Python course. #Python #LearnPython #PythonForBeginners #Coding #Programming
Introduction
Before you can write a single useful program, you need to understand how Python does math and how it makes decisions. That sounds basic, but it's not — arithmetic and logical operators are the foundation underneath every conditional, every loop, every algorithm you'll ever write. When you're solving a LeetCode problem and you need to check if a number is even, split an array in half, or compare two values, you're leaning directly on the concepts in this lesson.
Interviewers rarely ask "what does the modulo operator do" as a standalone question, but they absolutely test whether you use it correctly under pressure. A candidate who fumbles floor division versus true division, or who writes if x = 5 instead of if x == 5, loses credibility fast — not because the mistake is complex, but because it signals shaky fundamentals. Getting this right now means you stop thinking about syntax and start thinking about problems.
Problem Overview
There isn't a single "problem" to solve here in the traditional algorithmic sense. Instead, think of this as building the vocabulary and toolkit you'll use to solve every future problem. Specifically, we need to understand:
- The arithmetic operators (
+,-,*,/,//,%,**) and what each one actually returns - The difference between true division and floor division
- What modulo (
%) really means and why it's the backbone of even/odd checks - Comparison operators (
==,!=,<,>,<=,>=) and how they always resolve toTrueorFalse - Logical operators (
and,or,not) and how they combine boolean conditions - Operator precedence — the order Python follows when an expression has multiple operators
- Type conversion between
int,float, andstr, including Python's automatic conversions - Why floating-point math sometimes produces "weird" results, and how to compare floats safely
By the end, you should be able to look at any expression and predict exactly what Python will compute — step by step, in the correct order.
Example
Let's ground this in a concrete example instead of abstract rules.
result = 2 + 3 * 4 > 10
print(result)
Output: True
Walk through it with me: Python doesn't read left to right like English. It follows precedence rules, so multiplication happens before addition, and both happen before the comparison. First 3 * 4 becomes 12. Then 2 + 12 becomes 14. Finally, 14 > 10 evaluates to True. One expression, three separate evaluation steps, each producing an intermediate value that feeds the next.
Here's a second example that trips up almost every beginner:
print(7 / 2) # 3.5
print(7 // 2) # 3
print(7 % 2) # 1
print(8 / 2) # 4.0 <- not 4!
/ always returns a float, even when the division is exact. // throws away the fractional part and rounds toward negative infinity. % gives you exactly what's left over after that flooring happens. Notice that 7 // 2 and 7 % 2 are two halves of the same operation — 7 = 2 * 3 + 1.
Intuition
Here's how an experienced engineer thinks about operators before writing any code: every operator answers one specific question, and your job is to match the operator to the question you're actually asking.
If the question is "how many whole groups fit?" — like counting how many full boxes you can pack — you want floor division. If the question is "what's left over after grouping?" — like figuring out how many items don't fit in a full box — you want modulo. If the question is "what's the precise real-world value?" — like splitting a restaurant bill — you want true division.
Comparisons and logical operators follow the same pattern. A comparison operator answers a single yes/no question. Logical operators let you combine multiple yes/no questions into one final answer, the same way a bouncer combines "are you old enough" and "do you have ID" into a single admit/deny decision. and requires every condition to hold. or requires just one. not flips whatever it's given.
The reason precedence matters is that Python has to resolve one operator at a time, and it needs a deterministic rule for which operator goes first when there's no parentheses to guide it. The order mirrors what you learned as PEMDAS in school: parentheses, then exponents, then multiplication/division, then addition/subtraction, then comparisons, then logical operators last. Once you internalize that order, you can predict the output of any expression without running it.
Brute Force Solution
There isn't a "brute force vs optimal" split for this lesson the way there is for an algorithm problem — but there is a brute-force mental habit worth calling out: manually tracing an expression left to right without knowing precedence rules.
Idea: Evaluate operators in the order they appear in the text, ignoring precedence.
Algorithm: Read the expression left to right, apply each operator as you encounter it.
Disadvantage: This gives the wrong answer. For 2 + 3 * 4, reading left to right naively gives (2 + 3) * 4 = 20, but Python actually computes 2 + (3 * 4) = 14. This "brute force" mental model is a common source of bugs for beginners who haven't yet memorized precedence.
Time/Space Complexity: Not applicable — this is a conceptual error, not an algorithm.
Optimal Solution
The reliable approach is to apply Python's actual precedence order, and when in doubt, use parentheses to make your intent explicit rather than relying on memorized rules.
Here's the precedence order, highest to lowest:
| Priority | Operators | Category |
|---|---|---|
| 1 (highest) | () |
Parentheses |
| 2 | ** |
Exponentiation |
| 3 | *, /, //, % |
Multiplication/Division |
| 4 | +, - |
Addition/Subtraction |
| 5 | ==, !=, <, >, <=, >= |
Comparison |
| 6 | not |
Logical NOT |
| 7 | and |
Logical AND |
| 8 (lowest) | or |
Logical OR |
Evaluation happens in passes: Python scans for the highest-priority operator still remaining, collapses it into a value, then repeats until one value is left. This is exactly what we traced in the 2 + 3 * 4 > 10 example above — multiplication collapses first, then addition, then comparison.
The senior-engineer habit that beats memorizing this table perfectly: wrap ambiguous expressions in parentheses. (2 + 3) * 4 costs nothing to type and removes all doubt for the next reader — including future you.
Python Code
import math
def is_even_and_greater_than(n: int, threshold: int) -> bool:
"""Check whether n is even and strictly greater than threshold."""
return n % 2 == 0 and n > threshold
def safe_divide(a: float, b: float) -> float:
"""True division that raises a clear error instead of crashing on zero."""
if b == 0:
raise ZeroDivisionError("cannot divide by zero")
return a / b
def floats_are_equal(a: float, b: float) -> bool:
"""Compare floats safely instead of using ==."""
return math.isclose(a, b)
def convert_to_int(value: str) -> int:
"""Convert a numeric string to int, rounding decimals properly."""
return round(float(value))
Code Walkthrough
n % 2 == 0checks evenness — any number modulo 2 is either 0 (even) or 1 (odd). This single operator is the standard even/odd check you'll reuse constantly.and n > thresholdchains a second condition; both must beTruefor the whole expression to beTrue.safe_dividechecks for zero before dividing, since Python raisesZeroDivisionErrorona / 0and it's better to fail with an intentional, readable error.math.isclose(a, b)replacesa == bfor floats. Because floats are binary approximations, direct equality checks are unreliable —isclosechecks that two values are "close enough" within a tolerance instead of bit-for-bit identical.round(float(value))first converts the string to a float, then rounds to the nearest integer — this avoids the common mistake of usingint()on a decimal, which truncates instead of rounding.
Dry Run
Let's trace is_even_and_greater_than(14, 10):
n % 2→14 % 2→00 == 0→Truen > threshold→14 > 10→TrueTrue and True→True
Function returns True, because 14 is even and greater than 10.
Now is_even_and_greater_than(7, 10):
7 % 2→11 == 0→False- Python short-circuits
andhere — since the left side is alreadyFalse, it never bothers evaluatingn > threshold. - Result:
False
That short-circuit behavior is worth remembering: and stops as soon as it hits a False, and or stops as soon as it hits a True. This matters for performance and for writing conditions that avoid errors (like checking x != 0 and 10 / x > 1 safely).
Complexity Analysis
Every operator discussed here — arithmetic, comparison, and logical — runs in O(1) time and O(1) space for fixed-size numeric types (int, float). Python doesn't loop or recurse to evaluate a + b or a % b; these map to a constant number of low-level operations. This holds true regardless of the size of the expression's result, though extremely large integers in Python (arbitrary precision) can technically take longer for very large magnitudes — a detail that rarely matters outside of cryptography-scale numbers.
Alternative Solutions
For the "check even and greater than threshold" example, an alternative using bitwise AND is worth knowing: n & 1 == 0 also checks evenness, since the last bit of a binary number is 0 for even numbers. It's marginally faster than % in some languages, but in Python the performance difference is negligible, and n % 2 == 0 is far more readable. Prefer % unless you're working in a domain where bitwise operations are already the established idiom (like flags or masks).
Edge Cases
- Zero division:
5 / 0and5 // 0both raiseZeroDivisionError— always guard against a zero divisor. - Negative floor division:
-7 // 2gives-4, not-3, because floor division always rounds toward negative infinity, not toward zero. - Negative modulo:
-7 % 2gives1in Python (not-1as in some other languages), because Python's modulo result always matches the sign of the divisor. - Float precision:
0.1 + 0.2 == 0.3evaluates toFalsedue to binary floating-point representation — always usemath.isclosefor float comparisons. - Type mismatch:
"5" + 3raisesTypeError— Python won't silently convert strings and numbers for+.
Common Mistakes
- Using
=(assignment) when you mean==(comparison) — this is a syntax error in anifstatement, but can silently reassign a variable in other contexts. - Assuming
/and//behave the same —/always returns a float,//returns a floored result. - Using
int()to round a float —int(3.9)gives3, not4, because it truncates rather than rounds. Useround()instead. - Comparing floats with
==— always usemath.isclose()to avoid false negatives from binary precision errors. - Forgetting operator precedence and assuming left-to-right evaluation —
2 + 3 * 4is14, not20. - Mixing types without converting —
"5" + 3crashes; you needint("5") + 3or"5" + str(3). - Dividing by zero without a guard, which crashes the program instead of failing gracefully.
Interview Questions
- What's the difference between
/and//in Python, and when would you use each? - How would you check if a number is even without using the modulo operator?
- Why shouldn't you compare two floats with
==? What's the alternative? - Explain Python's operator precedence for a mixed expression like
a + b * c > d and e. - What happens when you divide a negative number using floor division and modulo?
- How does Python's
and/orshort-circuiting affect program behavior and performance?
Similar Problems
- LeetCode 7 (Reverse Integer): relies heavily on
//and%to peel off digits one at a time. - LeetCode 9 (Palindrome Number): uses modulo and floor division to reverse digits without converting to a string.
- LeetCode 66 (Plus One): requires careful handling of carry logic, which depends on modulo/floor-division intuition.
- LeetCode 231 (Power of Two): tests understanding of modulo and bitwise operators for even/odd and power checks.
These all build directly on the arithmetic and modulo intuition from this lesson — if you understand why modulo isolates the last digit, these problems become mechanical instead of mysterious.
Key Takeaways
- Arithmetic operators map almost exactly to what you learned in school, with
//and%as the two new, powerful additions. /always returns a float;//and%are a matched pair — one gives whole groups, the other gives the leftover.- Comparisons always resolve to
TrueorFalse, never anything else. andrequires everything to pass,orneeds just one,notflips the result — and bothand/orshort-circuit.- Precedence follows PEMDAS-style rules, with logical operators evaluated last — when in doubt, add parentheses.
- Never compare floats with
==; usemath.isclose()instead. int()truncates,round()rounds — know which one your problem actually needs.
Watch the Video
For the full step-by-step walkthrough with live examples and whiteboard-style tracing of expression evaluation, watch the video here: {LINK}
About the Series
This lesson is part of the Daily Python LeetCode series — a day-by-day walkthrough of Python fundamentals and interview-style problem solving, built for developers who want to go from "I know some Python" to "I can confidently solve problems under interview pressure." Each lesson builds directly on the last, so today's operators and expressions become tomorrow's building blocks for conditionals, loops, and full algorithms.
Call To Action
If this helped clarify how Python actually evaluates your code, subscribe on YouTube so you don't miss the next lesson, and subscribe to the Substack newsletter for the written breakdown delivered straight to your inbox. Drop a comment with the practice expression from tonight's homework — write one expression that checks whether a number is even and greater than ten — and share this with a fellow developer who's still getting tripped up by / vs //.
The solution
# "5" + 3 TypeError! convert first
print(int("5") + 3) # 8
print(int(3.9)) # 3, chopped, not rounded
print(round(3.9)) # 4, actual rounding
# print(10 / 0) ZeroDivisionErrorReady to try it yourself? Solve General problems with instant feedback in the practice sandbox.
Practice now →


