Python Programming
40 subscribers
5 photos
2 links
🐍 Python Programming | Code. Learn. Grow.

Welcome to Python Programming — your go-to Telegram community for mastering Python, from basics to advanced!
Download Telegram
📘 Day 10: Dictionaries: keys, values, and common methods

Dictionaries are one of Python’s core data structures. Think of a dictionary as a real‑world map: you look up a value (the value) by providing a unique identifier (the key). Under the hood, Python implements a dictionary as a hash table, which gives average‑case O(1) time for look‑ups, inserts, and deletions.

How a key works
- A key must be immutable (e.g., int, float, str, tuple of immutables).
- When you use a key, Python runs its __hash__ method to produce a hash code, then uses that code to decide where to store the value in the internal table.
- Two different objects can have the same hash (a collision). Python resolves collisions by chaining entries together, so lookup still stays fast.

Values can be any Python object: numbers, strings, lists, even other dictionaries.

Creating a dictionary

# A simple price‑list dictionary
prices = {
"apple": 0.60,
"banana": 0.40,
"cherry": 2.00
}


- The curly braces {} denote a dictionary literal.
- Each entry is written as key: value, separated by commas.
- Keys are strings here, but could be integers or tuples.

Accessing, adding, and updating

# Access a value – raises KeyError if the key is missing
apple_price = prices["apple"] # 0.60

# Safely get a value with a default – no exception
orange_price = prices.get("orange", 0.0) # 0.0

# Add a new entry or update an existing one
prices["date"] = 1.50 # adds 'date'
prices["banana"] = 0.45 # updates 'banana'


- prices["apple"] looks up the hash of "apple" and fetches the associated value.
- dict.get(key, default) first tries the normal lookup; if the key is absent it returns default instead of raising an error.

Removing items

# Remove a specific key, returning its value
removed = prices.pop("cherry") # removed == 2.00

# Remove an arbitrary (last) key‑value pair – useful for LIFO stacks
key, value = prices.popitem() # e.g., ('date', 1.50)

# Clear the whole dictionary
prices.clear() # now {}


- pop uses the key’s hash to locate the entry, removes it, and returns the value.
- popitem is fast because it doesn’t need to search; it just removes the last slot used.

Viewing the contents

keys_view   = prices.keys()     # dict_keys(['apple', 'banana'])
values_view = prices.values() # dict_values([0.60, 0.45])
items_view = prices.items() # dict_items([('apple', 0.60), ('banana', 0.45)])


- These methods return view objects that reflect the dictionary’s current state.
- They are iterable, so you can loop over them directly.

Common utility methods

- setdefault(key, default): returns the value for key if present; otherwise inserts key with default and returns default.
- update(other_dict): merges another dictionary (or iterable of key‑value pairs) into the current one, overwriting existing keys.
- copy(): shallow copy of the dictionary (new container, same values).

Why these methods exist
All of them rely on the same hashing mechanism. Because the hash of a key never changes during its lifetime, the dictionary can safely keep the entry at a fixed slot. Methods like update and setdefault are shortcuts that avoid writing explicit if … else checks, making code both clearer and more efficient.

A complete runnable example

(continued below 👇)
# -*- coding: utf-8 -*-
# Demonstrates creation, lookup, modification, and common methods

# 1️⃣ Create a dictionary of students and their grades
grades = {"Alice": 85, "Bob": 92, "Charlie": 78}

# 2️⃣ Access a grade safely
bob_grade = grades.get("Bob") # 92
dave_grade = grades.get("Dave", -1) # -1 (default because Dave isn't present)

# 3️⃣ Add a new student and update an existing one
grades["Dave"] = 88 # add
grades["Alice"] = 90 # update

# 4️⃣ Remove a student and retrieve what was removed
removed_grade = grades.pop("Charlie") # 78

# 5️⃣ Show the current keys, values, and items
print("Keys:", list(grades.keys())) # ['Alice', 'Bob', 'Dave']
print("Values:", list(grades.values())) # [90, 92, 88]
print("Items:", list(grades.items())) # [('Alice', 90), ('Bob', 92), ('Dave', 88)]

# 6️⃣ Merge another dictionary
extra = {"Eve": 95, "Frank": 80}
grades.update(extra)

# 7️⃣ Final state
print("Final dictionary:", grades)


Walk‑through
1. Create grades with three entries.
2. get fetches Bob’s grade; for Dave it returns -1 because the key is missing.
3. Direct assignment either adds a new key ("Dave") or overwrites an existing one ("Alice").
4. pop removes "Charlie" and gives back his grade, demonstrating safe deletion.
5. keys(), values(), items() each return a view; converting them to list makes the output readable.
6. update merges extra into grades, adding Eve and Frank.
7. The final print shows the dictionary after all operations.

Key take‑aways
- Keys must be hashable → immutable types.
- Lookup is fast because Python computes a hash and jumps directly to the slot.
- Methods (get, setdefault, pop, update, etc.) are built on the same hashing principle and give you concise, error‑free ways to work with the data.

Quick reference (bolded list)
- dict[key] – direct access (KeyError if missing)
- dict.get(key, default) – safe access with fallback
- dict[key] = value – add or update
- dict.pop(key) – remove specific entry
- dict.popitem() – remove arbitrary entry (LIFO)
- dict.clear() – empty the dictionary
- dict.keys(), dict.values(), dict.items() – views of contents
- dict.update(other) – merge dictionaries
- dict.copy() – shallow copy

Understanding these fundamentals will make you comfortable handling any associative data in Python.
❤1
Which dictionary method returns a view of (key, value) pairs?
Anonymous Quiz
0%
keys()
0%
values()
100%
items()
0%
get()
📘 Day 11: Sets and basic set operations

What is a set?
A set in Python is an unordered collection that stores *unique, hashable items*.
Because order is not kept, you cannot rely on an index to retrieve an element – you ask the set “does this value exist?”. Internally Python stores a set as a hash table, which gives average‑case O(1) time for membership tests, insertions and deletions.

Creating sets
- {1, 2, 3} creates a set literal with three elements.
- set() creates an empty set – the literal {} would make an empty dictionary, not a set.
- You can build a set from any iterable (list, tuple, string, etc.) with set(iterable); duplicate items are automatically discarded.

Why must elements be hashable?
A hashable object implements __hash__ and __eq__. The hash value decides where in the internal table the element lives. If two objects compare equal (a == b) they must also have the same hash, otherwise the table could store the same logical value twice – breaking the “unique” guarantee.

Basic set operations – each operation returns a new set (leaving the originals untouched) unless you use the in‑place variants (|=, &=, -= …).

- Union (A | B) – all elements that appear in either set.
- Intersection (A & B) – only elements common to both sets.
- Difference (A - B) – elements in A that are not in B.
- Symmetric difference (A ^ B) – elements that are in exactly one of the sets.

Membership tests
x in S evaluates to True if x is present. Because of the hash table, this test is extremely fast.

Mutating a set – you can add or discard elements after creation:
- S.add(x) – insert x (does nothing if already present).
- S.discard(x) – remove x if it exists; no error if it does not.
- S.remove(x) – like discard but raises KeyError when x is absent.

Set relationships – useful for logical comparisons:
- A <= B (or A.issubset(B)) – A is a subset of B.
- A >= B (or A.issuperset(B)) – A is a superset of B.
- A < B / A > B – strict subset/superset (they must not be equal).

Below is a complete, runnable example that demonstrates creation, the core operations, and mutation. Each line is explained in the comments.

# ----- sets_demo.py -----
# 1️⃣ Create sets from different sources
fruits = {"apple", "banana", "cherry"} # literal set
more_fruits = set(["banana", "date", "elderberry"]) # from a list (duplicates removed)
empty = set() # explicit empty set

print("Initial sets:")
print("fruits :", fruits)
print("more_fruits :", more_fruits)

# 2️⃣ Union – combine all unique items
all_fruits = fruits | more_fruits
print("\nUnion (fruits | more_fruits):", all_fruits)

# 3️⃣ Intersection – keep only what appears in both
common = fruits & more_fruits
print("Intersection (fruits & more_fruits):", common)

# 4️⃣ Difference – items only in fruits
only_fruits = fruits - more_fruits
print("Difference (fruits - more_fruits):", only_fruits)

# 5️⃣ Symmetric difference – items in exactly one set
sym_diff = fruits ^ more_fruits
print("Symmetric difference (fruits ^ more_fruits):", sym_diff)

# 6️⃣ Membership test – fast O(1) lookup
print("\nIs 'apple' in all_fruits?", "apple" in all_fruits)

# 7️⃣ Mutating the set – add and discard
all_fruits.add("fig")
print("After adding 'fig':", all_fruits)

all_fruits.discard("banana") # safe removal
print("After discarding 'banana':", all_fruits)

# 8️⃣ Subset / superset checks
print("\nIs fruits a subset of all_fruits?", fruits <= all_fruits)
print("Is more_fruits a superset of common?", more_fruits >= common)

# 9️⃣ Iterate over a set – order is arbitrary
print("\nIterating over all_fruits:")
for item in all_fruits:
print("-", item)


(continued below 👇)
Walk‑through of the example
1️⃣ Creation – fruits uses a literal, more_fruits converts a list (duplicates are removed automatically), and empty shows the correct way to start with no elements.
2️⃣ Union (|) builds a new set containing every fruit that appears in either source. Because sets ignore order, the printed order may differ each run.
3️⃣ Intersection (&) keeps only the fruit that both collections share ("banana").
4️⃣ Difference (-) returns what is exclusive to fruits.
5️⃣ Symmetric difference (^) gives everything that is not shared – the complement of the intersection.
6️⃣ Membership – in checks presence instantly.
7️⃣ Mutation – add inserts a new element; discard removes safely without raising an error if the element is missing.
8️⃣ Subset / superset – relational operators (<=, >=) answer logical containment questions.
9️⃣ Iteration – you can loop over a set, but the order you receive items in is undefined.

Understanding why each operation works comes down to the hash table: when you call fruits | more_fruits, Python walks through the underlying tables, copies each unique hash bucket into a new table, and therefore guarantees no duplicates and O(len(A)+len(B)) time.

Feel free to copy the script into a file named sets_demo.py and run python sets_demo.py to see the output yourself. Experiment by adding or removing elements, or by using other operators (&=, |=, -=) to modify a set in place.

Key take‑aways
- Sets store unique, hashable items and are unordered.
- Basic operations (|, &, -, ^) return new sets; in‑place versions end with =.
- Membership tests are O(1) thanks to hashing.
- Use set() for an empty set; {} creates a dictionary.

Enjoy leveraging sets for tasks like deduplication, fast look‑ups, and mathematical‑style data analysis!
Which expression returns a new set containing elements that are in set A but not in set B?
Anonymous Quiz
0%
A
100%
B
0%
A & B
0%
A - B
0%
A ^ B
📘 Day 12: Conditionals: if, elif, else

Conditionals let a program choose different paths based on data.
In Python the three building blocks are if, elif, and else.

When Python reaches an if statement it evaluates the expression that follows.
If that expression is truthy (anything that is not False, 0, "", [], {}, None, etc.) the indented block right after the if runs once, then the whole conditional chain stops.
If the expression is falsy, Python skips that block and checks the next elif (short for “else if”).
Only the first block whose condition is true executes; all later blocks are ignored.
If none of the conditions are true, the else block runs – it is the fallback.

Why does indentation matter?
Python uses indentation to define code blocks. The interpreter groups every line that is indented the same amount under the preceding statement (if, elif, else, for, def, …). This eliminates the need for curly braces and makes the structure visible at a glance.

Key concepts to remember

- Truthiness – Python treats many values as true or false without explicit comparison.
Example: if []: is false, if [1]: is true.
- Comparison operators – ==, !=, <, >, <=, >= produce a Boolean (True or False).
- Logical operators – and, or, not combine or invert Boolean results, and they short‑circuit (stop evaluating as soon as the outcome is known).
- Order of checks – Place the most specific or most likely‑true conditions first to avoid unnecessary work.
- Nesting – You can place another if‑elif‑else inside any block, but keep indentation clear to avoid confusion.

Below is a complete, runnable example that demonstrates all three keywords, truthiness, and early returns.

def categorize_age(age):
"""
Return a human‑readable category for a given age.
Demonstrates if‑elif‑else flow and early returns.
"""
# 1️⃣ First check for impossible values
if age < 0:
return "Invalid age"

# 2️⃣ Check youngest group
elif age < 13:
return "Child"

# 3️⃣ Teenagers
elif age < 20:
return "Teenager"

# 4️⃣ General adult range
elif age < 65:
return "Adult"

# 5️⃣ Everyone older than 64
else:
return "Senior"

# Demo: run the function with a variety of ages
for a in [-5, 5, 16, 30, 70]:
result = categorize_age(a)
print(f"{a:>3} → {result}")


Walk‑through

1. Function definition – def categorize_age(age): creates a reusable block that receives one argument, age.
2. Docstring – The triple‑quoted string explains what the function does; it doesn’t affect execution but is good practice.
3. First if – if age < 0: checks for negative numbers.
- If True, return "Invalid age" exits the function immediately; none of the later checks run.
4. First elif – elif age < 13: runs only if the previous condition was false.
- If the age is between 0 and 12 inclusive, the function returns "Child" and stops.
5. Second elif – elif age < 20: catches ages 13‑19.
6. Third elif – elif age < 65: catches ages 20‑64.
7. else – If every previous test failed (meaning age is 65 or higher), the block after else: runs, returning "Senior".

The for loop at the bottom simply prints the result for several test ages, showing how each branch behaves.

Common pitfalls

(continued below 👇)
- Missing indentation – Forgetting to indent the block after if will raise an IndentationError.
- Using = instead of == – = assigns a value; == compares. Accidentally writing if age = 10: is a syntax error.
- Overlapping conditions – If you write elif age < 20: before elif age < 13:, the second will never be reached because any age < 13 is already caught by the first elif. Order matters!

When to prefer if‑elif‑else over multiple ifs

- Use a single chain (if‑elif‑else) when the conditions are mutually exclusive – you only need one branch.
- Use separate if statements when multiple branches might be true and you want all of them to execute.

By mastering these rules, you’ll be able to write clear, predictable decision logic in any Python program.
What will the function `categorize_age(20)` return?
Anonymous Quiz
0%
Invalid age
0%
Child
0%
Teenager
0%
Adult
📘 Day 13: Comparison and logical operators (and, or, not)

Comparison operators let you ask how two values relate to each other.
When Python evaluates an expression like a == b it does not return the numbers, it returns a Boolean value – either True or False.

The six basic comparison symbols are:

== – equal
!= – not equal
> – greater than
< – less than
>= – greater‑or‑equal
<= – less‑or‑equal

Why does 5 > 3 become True? Python compares the binary representation of the numbers internally and decides which one has the larger magnitude. The result of the comparison is stored as a bool object, a subclass of int (True is 1, False is 0). This lets you use the result directly in control flow (if, while) or as part of larger logical statements.

Logical operators combine those Boolean results.

and – returns True only if* both operands are True.
Python evaluates the left side first; if it is False it short‑circuits and skips the right side because the whole expression can never become True.

or – returns True if at least one* operand is True.
It also short‑circuits: if the left side is True, Python never evaluates the right side.

* not – a unary operator that flips a Boolean value: not True → False.

The precedence order is not > and > or. Parentheses let you override it, just like in arithmetic.

Putting it together – a realistic example

# Determine if a user can access premium content
age = 22
has_subscription = False
is_employee = True

# Must be at least 18 AND (have a subscription OR be an employee)
can_access = (age >= 18) and (has_subscription or is_employee)

print("Access granted?" , can_access)


Walk‑through

1. age >= 18 → 22 >= 18 → True
Python compares the two integers and produces a Boolean.

2. has_subscription or is_employee →
First part: has_subscription is False. Because it is False, or evaluates the right side.
Second part: is_employee is True → the whole or expression becomes True.

3. The outer and now sees True and True → True.
Both sides are true, so the combined condition is true.

4. can_access stores that Boolean, and the print statement shows Access granted? True.

If you changed age to 16, the first comparison would be False. Because and short‑circuits, Python would skip the whole right side and can_access would be False immediately.

Common pitfalls

* Using = instead of == – = assigns, == compares.
* Chaining comparisons without parentheses – Python allows a < b < c, which means a < b and b < c.
* Relying on truthy/falsy values – non‑Boolean objects (e.g., empty list [] or number 0) are treated as False in logical contexts, which can be handy but sometimes confusing.

Understanding why Python returns Booleans and how short‑circuit evaluation works lets you write more efficient and readable conditions. Practice combining them, and you’ll soon master decision‑making in code.
📘 Day 14: for loops

For loops are one of the most fundamental control structures in Python. They let you repeat a block of code for each item in a collection, called an iterable. Understanding why they work the way they do will make you write clearer, more efficient code.

1️⃣ What is an iterable?
An iterable is any object that can return its items one at a time, producing an iterator when you call iter() on it. Common iterables:
list, tuple, string, range, dict, set, file objects.

When a for loop starts, Python internally does three steps:

1. Calls iter() on the given object → gets an iterator.
2. Calls next() on that iterator → fetches the first item.
3. Executes the loop body with that item, then repeats step 2 until StopIteration is raised.

Because this logic is hidden, you only write for item in iterable: and Python handles the rest.

2️⃣ Basic syntax

for <variable> in <iterable>:
<block of code>


- <variable> receives each element one by one.
- The block is indented (usually 4 spaces) and runs for every element.

3️⃣ The simplest example – counting numbers

for i in range(5):
print(i)


What happens:
1. range(5) creates an iterable that yields 0, 1, 2, 3, 4.
2. The loop assigns i = 0 then runs print(i).
3. It repeats until the last value (4) is printed, then exits.

Why range? It’s a lazy iterable – it doesn’t build a full list in memory; it generates numbers on the fly, which is efficient for large sequences.

4️⃣ Looping over collections

fruits = ['apple', 'banana', 'cherry']
for fruit in fruits:
print('I like', fruit)


- The list fruits is an iterable.
- Each iteration binds fruit to the next element.
- You can modify the element or use it in any expression.

5️⃣ Getting the index with enumerate
Often you need both the position and the value:

for idx, fruit in enumerate(fruits, start=1):
print(f'{idx}. {fruit}')


- enumerate wraps any iterable and yields pairs (index, value).
- start=1 makes indexing human‑friendly (1‑based).

6️⃣ Parallel iteration with zip
When you have two (or more) iterables of the same length:

colors = ['red', 'yellow', 'red']
for fruit, color in zip(fruits, colors):
print(f'{fruit} is {color}')


- zip produces tuples (fruit, color) for each position.
- The loop stops at the shortest iterable, preventing IndexError.

7️⃣ Controlling the loop: break, continue, and else
- break exits the loop immediately.
- continue skips the rest of the current iteration and goes to the next.
- An else block runs only if the loop completed normally (no break).

total = 0
for i in range(1, 4): # 1, 2, 3
total += i
if i == 2:
continue # skip the rest for i==2
else:
total *= 2 # runs because no break occurred
print(total) # -> 12


Why the else? It lets you differentiate between “finished all items” and “stopped early with a break”.

8️⃣ A complete, runnable example

(continued below 👇)
# -*- coding: utf-8 -*-
# Demonstrates various for‑loop features

fruits = ['apple', 'banana', 'cherry']
prices = [0.99, 0.59, 1.29]

print('--- List each fruit with its price ---')
for fruit, price in zip(fruits, prices):
print(f'{fruit.title():<6} costs ${price:.2f}')

print('\n--- Show index and fruit, stop at banana ---')
for idx, fruit in enumerate(fruits):
if fruit == 'banana':
print('Found banana, stopping loop.')
break
print(f'{idx}: {fruit}')

print('\n--- Sum of prices, with else clause ---')
total = 0
for p in prices:
total += p
else: # runs because we never break
print(f'Total price is ${total:.2f}')


Walk‑through:
1. zip(fruits, prices) creates pairs: ('apple',0.99), ('banana',0.59), ('cherry',1.29).
The loop prints each nicely formatted line.
2. enumerate(fruits) yields (0,'apple'), (1,'banana'), (2,'cherry').
When 'banana' is found, break stops the loop; the else after the loop (not shown here) would be skipped.
3. The final loop adds each price to total. Because we never break, the else block executes, printing the sum.

Run this script – it will print a clear demonstration of each concept.

9️⃣ Common pitfalls
- Modifying the iterable while looping can lead to unexpected behavior. Iterate over a copy (for x in mylist[:]) if you need to remove items.
- Using range with mutable defaults: for i in range(len(list)): is fine, but prefer direct iteration (for item in list:) for readability.
- Forgot the colon after the for statement – Python will raise a SyntaxError.

🔑 Bottom line
A for loop abstracts the iterator protocol, letting you focus on what to do with each element rather than how to fetch it. Mastering range, enumerate, zip, and loop‑control statements turns a simple repetition into a powerful tool for data processing, algorithmic logic, and clean code.
What value does the variable `total` have after this code runs?
Anonymous Quiz
0%
12
50%
10
50%
6
0%
8
📘 Day 15: while loops

A while loop lets you repeat a block of code as long as a condition stays true. It’s the most direct way to create a loop that depends on a condition that may change inside the loop body.

Why it works – Python evaluates the condition expression before each iteration.
- If the condition is truthy (anything that evaluates to True), the body runs.
- After the body finishes, Python goes back to re‑evaluate the condition.
- When the condition becomes falsy (False, 0, empty collection, None, etc.) the loop stops and execution continues after the loop.

This “check‑first” behaviour is different from a for‑loop, which iterates over a known sequence. With a while‑loop you often don’t know in advance how many times you’ll need to repeat – the loop stops exactly when the condition flips.

Anatomy of a while loop

while <condition>:
<body>


- while – keyword that starts the loop.
- <condition> – any expression that returns a Boolean value.
- : – colon marks the start of the indented block.
- <body> – one or more indented statements that run each time the condition is true.

If the body never changes the condition, you get an infinite loop – the program will never exit the loop on its own. To avoid that, you usually:
- Update a variable inside the body, or
- Use break to exit early, or
- Use continue to skip the rest of the current iteration and re‑check the condition.

A complete, runnable example

# Countdown from 5 to 0 using a while loop
counter = 5 # start value
while counter >= 0: # condition: keep looping while counter is 0 or more
print(f"Counter is {counter}")
counter -= 1 # decrease counter by 1 each iteration
else:
print("Loop finished!") # this runs once after the condition becomes false


Walk‑through

1. counter = 5 – Initializes a variable that the loop will monitor.
2. while counter >= 0: – The loop will continue as long as counter is greater than or equal to 0.
3. print(f"Counter is {counter}") – Shows the current value each time the loop runs.
4. counter -= 1 – Decrements counter. This is the crucial step that eventually makes the condition false; without it, the loop would never stop.
5. else: – The else‑clause of a while loop executes once, after the condition becomes false unless the loop is exited with break. It’s handy for cleanup or final messages.
6. print("Loop finished!") – Runs after the loop ends, confirming successful termination.

Running this script prints:

Counter is 5
Counter is 4
Counter is 3
Counter is 2
Counter is 1
Counter is 0
Loop finished!


Common patterns & pitfalls

- Sentinel loop – keep reading input until a special value (the sentinel) appears.



word = ""
while word != "quit":
word = input("Type a word (or 'quit' to stop): ")
print("You typed:", word)


- Infinite loop with break – useful when the exit condition is discovered inside the body.



while True:
data = fetch_next()
if data is None: # no more data
break
process(data)


- continue – skips to the next iteration, re‑evaluating the condition immediately.



i = 0
while i < 10:
i += 1
if i % 2 == 0: # skip even numbers
continue
print(i) # prints only odd numbers


- Truthiness matters – any non‑zero number, non‑empty container, or non‑False object counts as true.



items = [1, 2, 3]
while items: # loops while the list is not empty
print(items.pop()) # removes the last item each iteration


(continued below 👇)
- Avoiding off‑by‑one errors – ensure the condition and the update step move towards termination.

When to prefer a while loop

- Indeterminate repetitions – you don’t know ahead of time how many times you need to loop (e.g., waiting for user input, reading a file until EOF).
- Complex exit logic – the stop condition may depend on multiple variables updated inside the loop.
- Resource‑waiting loops – repeatedly check a condition (like a network response) until it becomes true.

Quick checklist before you run a while loop

- Is the condition initially true? If not, the loop body never runs.
- Will something inside the body eventually make the condition false? If not, you’ll have an infinite loop.
- Do you need an early exit? Use break.
- Do you need to skip the rest of the current iteration? Use continue.
- Do you want a final action after normal termination? Add an else clause.

Mastering while loops gives you fine‑grained control over program flow, especially in situations where the number of iterations is driven by dynamic data rather than a fixed collection. Practice by rewriting simple for loops as while loops and observe how the condition and updates interact. Happy looping!
📘 Day 16: break, continue, and the loop else clause

When you write a loop in Python you usually expect it to run from the first element to the last, doing the same block of code over and over.
Sometimes you need more control: stop early, skip the rest of the current iteration, or run a piece of code only if the loop wasn’t stopped early.
That’s what break, continue, and the loop‑else clause give you.

break – leaving the loop right now
When Python reaches a break, it immediately exits the innermost loop (whether for or while).
All remaining iterations are ignored, and execution continues with the first statement after the loop.

Why it works – A break raises a hidden internal exception that is caught by the loop machinery. The loop catches that exception, cleans up, and jumps out.

continue – skip to the next iteration
When Python sees a continue, it stops the current iteration right there and jumps to the top of the loop to evaluate the next item (or the loop condition again for a while). The code that follows continue inside the loop body is never run for that iteration.

Why it works – Internally Python raises a different hidden exception that tells the loop “start the next cycle now”. The loop catches it, skips the rest of the body, and proceeds.

else on a loop – run only if the loop finished normally
A loop can have an else block:

for item in iterable:
# loop body
else:
# runs when the loop **did NOT** encounter a break


The else block is executed after the loop finishes its natural course (i.e., the iterator is exhausted or the while condition became false). If a break occurs, the else block is skipped.

Why it works – After each iteration the loop checks two things:
1. Did we exit because of break? → skip else.
2. Did we run out of items / condition became false? → run else.

Putting it all together – a complete example

numbers = [5, 12, 7, -3, 0, 9, 4]

print("Scanning numbers...")

for n in numbers:
# 1️⃣ Skip negative numbers – we don’t want to process them
if n < 0:
print(f" {n} is negative → continue")
continue # jump to the next item

# 2️⃣ Stop the whole scan as soon as we hit zero
if n == 0:
print(" Zero found! → break")
break # leave the loop completely

# Normal processing for positive, non‑zero numbers
print(f" {n} is ok, processing...")

else:
# This runs only if we never hit the `break`
print("All numbers processed without hitting zero.")

print("Done.")


Walk‑through

1. for n in numbers: – starts iterating over the list.
2. if n < 0: – detects a negative value.
continue prints a message and jumps to the next element, so the rest of the body (print of “ok”) is skipped for that iteration.
3. if n == 0: – when a zero appears, we print a message and break. The loop ends immediately, so the else block is not executed.
4. For any other positive number, we reach the regular print and continue looping.
5. If the loop runs through the whole list without ever hitting break, the else: block runs, confirming a “clean” finish.
6. Finally, print("Done.") runs after the loop (whether we broke out early or not).

What you’ll see when you run it

Scanning numbers...
5 is ok, processing...
12 is ok, processing...
7 is ok, processing...
-3 is negative → continue
Zero found! → break
Done.


Notice that the else message never appears because we hit break at the zero.

When to use each construct

(continued below 👇)
- break – when a condition means “the rest of the work is pointless”. Typical examples: searching for an item, validating input, early exit on error.
- continue – when you want to ignore certain items but keep scanning the rest. Useful for filtering inside a loop without extra nesting.
- else on loops – when you need a “no‑break” confirmation. Common in search patterns: “found it → break; otherwise → after‑loop else means not found”.

Quick comparison

- break → stop the loop now.
- continue → skip the rest of this iteration, go to next.
- else → run after the loop only if no break happened.

Mastering these three tools lets you write loops that are both expressive and efficient, avoiding extra flags or nested conditionals.
What happens to a loop's `else` block if a `break` statement is executed inside the loop?
Anonymous Quiz
50%
It still runs after the loop
0%
It runs only once before the break
0%
It is skipped entirely
50%
It runs only if the loop is a `while`