AmouAI Hub/Courses/Programming Fundamentals/Day 2
Operators, Expressions & Strings
Yesterday you stored values. Today you compute with them - and you meet the two operators (// and %) that quietly do half the work in every program you will ever write.
By the end of today you can
- Use every arithmetic operator correctly, including
//,%and** - Predict the result of any expression by applying operator precedence
- Build boolean expressions with
and,or,notand explain short-circuiting - State which values Python treats as falsy, and why
if x:beatsif x == True: - Index and slice strings, including with negative indices and steps
- Clean and reshape messy text with string methods
▶Today's videos
Watch each video, then work the matching sections below. Watching alone will not do it.
1Arithmetic, and the two operators that matter most
Six of the seven arithmetic operators are obvious. The other two, // and %, are the ones you will reach for constantly.
| Operator | Name | Example | Result |
|---|---|---|---|
+ | Add | 7 + 3 | 10 |
- | Subtract | 7 - 3 | 4 |
* | Multiply | 7 * 3 | 21 |
/ | True division | 7 / 3 | 2.3333333333333335 (always a float) |
// | Floor division | 7 // 3 | 2 (whole part only) |
% | Modulo | 7 % 3 | 1 (the remainder) |
** | Power | 7 ** 3 | 343 |
6 / 3 is 2.0, not 2. If you need a whole number, use //. And // floors toward negative infinity: -7 // 2 is -4, not -3.
Modulo is not a niche operator
% gives you the remainder. That one fact solves a surprising number of problems:
n % 2 == 0 # is n even?
n % 5 == 0 # is n a multiple of 5?
total % 60 # leftover seconds after taking out whole minutes
1234 % 10 # 4 - the last digit
1234 // 10 # 123 - everything except the last digit
(i + 1) % 7 # cycle 0,1,2,3,4,5,6,0,1,2... foreverTogether, // and % let you take a number apart:
total_seconds = 9045
hours = total_seconds // 3600 # 2
remaining = total_seconds % 3600 # 1845
minutes = remaining // 60 # 30
seconds = remaining % 60 # 45
print(f"{hours:02d}:{minutes:02d}:{seconds:02d}")Precedence
Python evaluates in this order, highest first: **, then unary -, then
* / // %, then + -, then comparisons, then not, then
and, then or.
2 + 3 * 4 ** 2 % 5 is legal and correct and nobody reading it is confident. 2 + ((3 * (4 ** 2)) % 5) costs you six characters and removes all doubt. If you had to pause to work out the order, add the parentheses.
2Comparison and boolean logic
Comparisons produce booleans. Booleans combine. That combination is the engine of every decision your programs will make from tomorrow onward.
7 == 7 # True - equal to
7 != 3 # True - not equal to
7 > 3 # True
7 <= 7 # True
# Chained comparisons read exactly like maths
score = 85
print(0 <= score <= 100) # True== asks "are these the same value?" is asks "are these literally the same object in memory?" They agree often enough to fool you and disagree often enough to waste your afternoon. Rule: use == for everything except x is None.
and, or, not
a | b | a and b | a or b | not a |
|---|---|---|---|---|
| True | True | True | True | False |
| True | False | False | True | False |
| False | True | False | True | True |
| False | False | False | False | True |
Short-circuiting
Python stops evaluating as soon as the answer is certain. False and anything is
False, so the right side is never even looked at.
count = 0
total = 10
# Without short-circuiting this would crash with ZeroDivisionError.
# Because count != 0 is False, Python never evaluates the division.
if count != 0 and total / count > 5:
print("high average")
else:
print("no data or low average")Truthiness
Every value can be used where a boolean is expected. These are the falsy ones, and everything else is truthy:
bool(0) # False
bool(0.0) # False
bool("") # False - empty string
bool([]) # False - empty list
bool({}) # False - empty dict
bool(None) # False
bool(-1) # True - any non-zero number
bool("0") # True - a non-empty string, even if it says "0"
bool("False") # True - still just text
bool(" ") # True - a space is a characterThey are not the same. if x: asks "is x truthy?" and works for any type. if x == True: asks "is x equal to the boolean True?" - which is False for x = "hello". Use the short form.
Augmented assignment
total = 10
total += 5 # same as total = total + 5 -> 15
total -= 3 # 12
total *= 2 # 24
total //= 5 # 4
total **= 2 # 16
print(total)3Indexing and slicing strings
Strings are sequences of characters, and every character has a position. Two positions, actually - and knowing that kills off-by-one errors for good.
Positions count from zero. Negative positions count from the end, starting at
-1.
word = "PYTHON"
print(word[0]) # 'P' first character
print(word[5]) # 'N' sixth character
print(word[-1]) # 'N' last character
print(word[-2]) # 'O' second from the end
print(len(word)) # 6
print(word[6]) # IndexError - there is no position 6Slicing: [start:stop:step]
start is included, stop is excluded. Think of the indices as sitting
between the characters, like fence posts - that is why word[0:3] gives you three
characters, not four.
s = "PROGRAMMING"
s[0:4] # 'PROG' positions 0,1,2,3
s[:4] # 'PROG' start defaults to 0
s[4:] # 'RAMMING' stop defaults to the end
s[:] # whole string
s[-4:] # 'MING' last four
s[:-4] # 'PROGRAM' everything except the last four
s[::2] # 'PORMIG' every second character
s[::-1] # 'GNIMMARGORP' reversed
s[20:30] # '' out of range slicing gives an empty string, no errors[99] crashes. s[99:200] quietly gives you ''. That asymmetry surprises people - and it is occasionally exactly what you want.
4Strings are immutable
You cannot change a string. You can only build a new one. Once that lands, a whole class of bugs disappears.
name = "amin"
name[0] = "A" # TypeError: 'str' object does not support item assignmentEvery string method returns a new string and leaves the original alone. This is the single most common Day 2 mistake:
name = "amin"
name.upper() # this computes "AMIN" and throws it away
print(name) # 'amin' - nothing changed
name = name.upper() # THIS is how you keep the result
print(name) # 'AMIN' If a line is just text.strip() with nothing on the left of an =, that line does nothing at all. Python will not warn you.
5The string methods you will actually use
There are dozens. These fifteen cover almost everything you will do this course.
| Method | What it does | Example |
|---|---|---|
.upper() / .lower() | Change case | "Hi".upper() → 'HI' |
.title() | Capitalise Each Word | "amin a".title() → 'Amin A' |
.strip() | Remove whitespace from both ends | " hi ".strip() → 'hi' |
.replace(a, b) | Swap every occurrence | "a-b".replace("-", " ") → 'a b' |
.split(sep) | Break into a list of pieces | "a,b,c".split(",") → ['a','b','c'] |
sep.join(parts) | Glue pieces back together | "-".join(["a","b"]) → 'a-b' |
.find(x) | Position of x, or -1 | "hello".find("l") → 2 |
.count(x) | How many times x appears | "hello".count("l") → 2 |
.startswith(x) / .endswith(x) | Boolean test | "cat.py".endswith(".py") → True |
.isdigit() | All characters are digits | "42".isdigit() → True |
.isalpha() | All characters are letters | "a1".isalpha() → False |
x in s | Is x somewhere inside s | "ell" in "hello" → True |
.split() and .join() are inverses, and together they do more work than any
other pair of string methods:
raw = " jOHN smith "
cleaned = raw.strip() # 'jOHN smith'
parts = cleaned.split() # ['jOHN', 'smith'] <- split() with no argument
# splits on ANY run of whitespace
first = parts[0].title() # 'John'
last = parts[1].title() # 'Smith'
print(f"{last}, {first}") # 'Smith, John'
print("-".join(parts)) # 'jOHN-smith' A worked program
# password_strength.py
password = "Sunshine2026"
long_enough = len(password) >= 8
has_digit = any(ch.isdigit() for ch in password)
has_upper = password != password.lower()
has_lower = password != password.upper()
score = long_enough + has_digit + has_upper + has_lower # booleans add as 1 and 0
print(f"Password: {password}")
print(f" 8+ characters : {long_enough}")
print(f" has a digit : {has_digit}")
print(f" has upper : {has_upper}")
print(f" has lower : {has_lower}")
print(f" score : {score}/4")True + True is 2. That is why long_enough + has_digit + ... counts how many conditions passed. It is a genuinely useful trick, not a party trick.
>_Python playground
A real Python interpreter running inside your browser. Nothing is installed, nothing is uploaded, nothing can break.
input(), comma separated →
✓Exercise set
Checked automatically the moment you submit. Work top to bottom — each one assumes the last. Your answers are saved in this browser.
Day 3 — Conditional Logic & Control Flow
Programs stop running straight through and start making decisions.