Match-Case, Nested If, Lists, Tuples & Sets
1. Match-Case Statement
Introduced in Python 3.10 β Think of it as a supercharged
switchstatement from other languages, but much more powerful.
Basic Syntax
match variable:
case value1:
# do something
case value2:
# do something else
case _:
# default β runs when nothing else matches
πΉ Example 1 β HTTP Status Codes (DevOps Classic!)
status_code = 404
match status_code:
case 200:
print(" OK β Request successful")
case 201:
print(" Created β Resource was created")
case 301:
print(" Moved Permanently")
case 400:
print(" Bad Request β Check your payload")
case 401:
print("π Unauthorized β Invalid credentials")
case 403:
print(" Forbidden β You don't have permission")
case 404:
print(" Not Found β Resource doesn't exist")
case 500:
print(" Internal Server Error")
case _:
print(f" Unknown status code: {status_code}")
Output:
π Not Found β Resource doesn't exist
Example 2 β Matching Multiple Values in One Case
day = "Saturday"
match day:
case "Monday" | "Tuesday" | "Wednesday" | "Thursday" | "Friday":
print("πΌ Work day β stand-up at 9am!")
case "Saturday" | "Sunday":
print("ποΈ Weekend β no deployments today!")
case _:
print("π€ Not a valid day")
Output:
ποΈ Weekend β no deployments today!
Example 3 β Matching Tuples (Coordinates / Commands)
command = ("move", 10, 20)
match command:
case ("move", x, y):
print(f" Moving to coordinates ({x}, {y})")
case ("shoot", direction):
print(f" Shooting {direction}")
case ("stop",):
print(" Stopping")
case _:
print(" Unknown command")
Output:
Moving to coordinates (10, 20)
πΉ Example 5 β Using if Guards in Match-Case
score = 85
match score:
case s if s >= 90:
print(f"Grade A β Excellent! ({s})")
case s if s >= 80:
print(f"Grade B β Good job! ({s})")
case s if s >= 70:
print(f"Grade C β Keep practicing ({s})")
case s if s >= 60:
print(f"Grade D β Study harder ({s})")
case _:
print(f"Grade F β Please retry ({score})")
Output:
Grade B β Good job! (85)
2. Nested If Statements
Nested if means placing one
ifblock inside another. Use it when decisions depend on previous decisions β like a decision tree.
Golden Rules for Nested Ifs:
- Keep nesting to max 3 levels β deeper = harder to read
- Consider early returns or match-case to flatten deep nesting
- Always add comments when logic is complex
πΉ Example 1 β Login System
username = "admin"
password = "secret123"
is_active = True
if username == "admin":
print("π€ Username recognized")
if password == "secret123":
print("π Password correct")
if is_active:
print("Login successful! Welcome, Admin.")
else:
print("Account is deactivated. Contact support.")
else:
print("Wrong password. Try again.")
else:
print("Username not found.")
Output:
Username recognized
Password correct
Login successful! Welcome, Admin.
Example 3 β Weather Advice App
temperature = 28
is_raining = False
is_sunny = True
if temperature > 30:
print("Very hot day!")
if is_sunny:
print("πΆοΈ Wear sunglasses and sunscreen.")
else:
print(" Hot and cloudy β stay hydrated.")
elif temperature >= 20:
print("Comfortable weather!")
if is_raining:
print("βοΈ Take an umbrella just in case.")
elif is_sunny:
print(" Great day to go outside!")
else:
print(" Mild and cloudy β enjoy the breeze.")
elif temperature >= 10:
print("Chilly weather")
if is_raining:
print(" Wear a raincoat and boots.")
else:
print("A jacket will do!")
else:
print(" Freezing! Stay indoors if possible.")
Output:
Comfortable weather!
Great day to go outside!
πΉ Example 4 β Number Classifier (Nested + Logical)
def classify_number(n):
if n > 0:
print(f"β
{n} is Positive")
if n % 2 == 0:
print(f" βββ Even number")
if n % 10 == 0:
print(f" βββ Also a multiple of 10!")
else:
print(f" βββ Odd number")
if n % 3 == 0:
print(f" βββ Also divisible by 3!")
elif n < 0:
print(f"β {n} is Negative")
if n % 2 == 0:
print(f" βββ Negative Even number")
else:
print(f" βββ Negative Odd number")
else:
print("βͺ It's Zero β neither positive nor negative")
classify_number(30)
classify_number(-7)
classify_number(0)
Output:
β
30 is Positive
βββ Even number
βββ Also a multiple of 10!
β -7 is Negative
βββ Negative Odd number
βͺ It's Zero β neither positive nor negative
πΉ Example 5 β DevOps Server Health Check
cpu_usage = 85 # percentage
memory_usage = 60 # percentage
disk_usage = 92 # percentage
is_production = True
print("=== Server Health Report ===")
if cpu_usage > 90:
print(" CRITICAL: CPU usage is dangerously high!")
elif cpu_usage > 75:
print("WARNING: CPU usage is elevated")
if is_production:
print(" Consider scaling up production servers NOW")
else:
print(" Monitor closely in staging")
else:
print(" CPU: Normal")
if memory_usage > 90:
print(" CRITICAL: Memory almost full! Risk of OOM crash.")
elif memory_usage > 70:
print(" WARNING: Memory usage is high")
else:
print(" Memory: Normal")
if disk_usage > 95:
print(" CRITICAL: Disk nearly full! Immediate action required.")
elif disk_usage > 80:
print(" WARNING: Disk usage above 80%")
if is_production:
print(" Run log cleanup script immediately!")
else:
print(" Clean up test artifacts")
else:
print(" Disk: Normal")
Output:
=== Server Health Report ===
WARNING: CPU usage is elevated
Consider scaling up production servers NOW
Memory: Normal
CRITICAL: Disk nearly full! Immediate action required.
3. Lists β The Swiss Army Knife
A list is an ordered, mutable (changeable), and allows duplicates collection.
Syntax:my_list = [item1, item2, item3]
πΉ Creating Lists
# Empty list
empty = []
# List of strings
fruits = ["apple", "banana", "cherry", "mango"]
# Mixed types list
mixed = [42, "hello", 3.14, True, None]
# Nested list (matrix)
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
# List using list() constructor
numbers = list(range(1, 11)) # [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
print(fruits) # ['apple', 'banana', 'cherry', 'mango']
print(numbers) # [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
print(matrix[1][2]) # 6
Indexing & Slicing
servers = ["web-01", "web-02", "db-01", "cache-01", "worker-01"]
# Positive indexing
print(servers[0]) # web-01 (first)
print(servers[-1]) # worker-01 (last)
print(servers[-2]) # cache-01 (second to last)
# Slicing [start:stop:step]
print(servers[1:3]) # ['web-02', 'db-01']
print(servers[:2]) # ['web-01', 'web-02'] (first 2)
print(servers[2:]) # ['db-01', 'cache-01', 'worker-01'] (from index 2)
print(servers[::2]) # ['web-01', 'db-01', 'worker-01'] (every other)
print(servers[::-1]) # Reversed list
All List Methods β Complete Reference
β append(item) β Add one item to the end
shopping = ["milk", "eggs"]
shopping.append("bread")
shopping.append("butter")
print(shopping) # ['milk', 'eggs', 'bread', 'butter']
β insert(index, item) β Add item at a specific position
queue = ["Alice", "Bob", "Dave"]
queue.insert(2, "Charlie") # Insert Charlie at index 2
print(queue) # ['Alice', 'Bob', 'Charlie', 'Dave']
queue.insert(0, "Zara") # Insert at the beginning
print(queue) # ['Zara', 'Alice', 'Bob', 'Charlie', 'Dave']
β extend(iterable) β Add multiple items at once
team_a = ["Alice", "Bob"]
team_b = ["Charlie", "Dave", "Eve"]
team_a.extend(team_b)
print(team_a) # ['Alice', 'Bob', 'Charlie', 'Dave', 'Eve']
# Also works with any iterable
scores = [90, 85]
scores.extend(range(80, 84)) # Adds 80, 81, 82, 83
print(scores) # [90, 85, 80, 81, 82, 83]
remove(item) β Remove first occurrence of a value
colors = ["red", "green", "blue", "green", "yellow"]
colors.remove("green") # Removes FIRST "green" only
print(colors) # ['red', 'blue', 'green', 'yellow']
# Safe removal with check
if "pink" in colors:
colors.remove("pink")
else:
print("β οΈ 'pink' not found in list")
β pop(index) β Remove and return item by index
stack = ["task1", "task2", "task3", "task4"]
last = stack.pop() # Removes and returns last item
print(last) # task4
print(stack) # ['task1', 'task2', 'task3']
second = stack.pop(1) # Remove and return index 1
print(second) # task2
print(stack) # ['task1', 'task3']
β clear() β Remove ALL items
temp_data = [1, 2, 3, 4, 5]
print(f"Before: {temp_data}") # Before: [1, 2, 3, 4, 5]
temp_data.clear()
print(f"After: {temp_data}") # After: []
π index(item) β Find the position of an item
fruits = ["apple", "banana", "cherry", "banana", "mango"]
pos = fruits.index("banana") # First occurrence
print(f"First 'banana' at: {pos}") # 1
pos2 = fruits.index("banana", 2) # Search starting from index 2
print(f"Second 'banana' at: {pos2}") # 3
# Safe search with try-except
try:
pos3 = fruits.index("grape")
except ValueError:
print("β 'grape' is not in the list")
π’ count(item) β Count how many times a value appears
votes = ["yes", "no", "yes", "yes", "no", "yes", "abstain"]
yes_count = votes.count("yes")
no_count = votes.count("no")
print(f"β
Yes: {yes_count}") # β
Yes: 4
print(f"β No: {no_count}") # β No: 2
print(f"π Result: {'YES wins!' if yes_count > no_count else 'NO wins!'}")
π sort() β Sort the list in-place
# Sorting numbers
scores = [45, 92, 78, 63, 88, 55, 100]
scores.sort()
print(f"Ascending: {scores}") # [45, 55, 63, 78, 88, 92, 100]
scores.sort(reverse=True)
print(f"Descending: {scores}") # [100, 92, 88, 78, 63, 55, 45]
# Sorting strings
names = ["Zara", "Alice", "Mike", "Bob", "Charlie"]
names.sort()
print(f"Alphabetical: {names}") # ['Alice', 'Bob', 'Charlie', 'Mike', 'Zara']
# Sort by key (e.g. string length)
names.sort(key=len)
print(f"By length: {names}") # ['Bob', 'Zara', 'Mike', 'Alice', 'Charlie']
π sorted() β Return a NEW sorted list (original unchanged)
original = [5, 2, 8, 1, 9, 3]
new_sorted = sorted(original)
print(f"Original: {original}") # [5, 2, 8, 1, 9, 3] (unchanged)
print(f"New Sorted: {new_sorted}") # [1, 2, 3, 5, 8, 9]
# Sort list of dicts by a key
students = [
{"name": "Alice", "grade": 88},
{"name": "Bob", "grade": 95},
{"name": "Carol", "grade": 72},
]
by_grade = sorted(students, key=lambda s: s["grade"], reverse=True)
for s in by_grade:
print(f" {s['name']}: {s['grade']}")
Output:
Bob: 95
Alice: 88
Carol: 72
π reverse() β Reverse the list in-place
countdown = [1, 2, 3, 4, 5]
countdown.reverse()
print(countdown) # [5, 4, 3, 2, 1]
# Also works with strings in a list
words = ["Hello", "World", "Python"]
words.reverse()
print(words) # ['Python', 'World', 'Hello']
π copy() β Create a shallow copy
original = [1, 2, 3, 4, 5]
# Wrong way β both variables point to SAME list
bad_copy = original
bad_copy.append(99)
print(original) # [1, 2, 3, 4, 5, 99] β Original was changed!
# Correct way β creates an INDEPENDENT copy
original2 = [10, 20, 30]
good_copy = original2.copy()
good_copy.append(99)
print(original2) # [10, 20, 30] β Original untouched
print(good_copy) # [10, 20, 30, 99]
π len() β Get the number of items (built-in)
students = ["Alice", "Bob", "Charlie", "Dave"]
print(f"Total students: {len(students)}") # 4
matrix = [[1, 2, 3], [4, 5, 6]]
print(f"Rows: {len(matrix)}") # 2
print(f"Cols: {len(matrix[0])}") # 3
4. Tuples β The Read-Only List
A tuple is an ordered, immutable (unchangeable), and allows duplicates collection.
Use tuples for data that should never change β coordinates, RGB colors, database records.
Syntax:my_tuple = (item1, item2, item3)
πΉ Creating Tuples
# Basic tuple
point = (10, 20)
# Single-item tuple β MUST have trailing comma!
single = (42,) # This is a tuple
not_a_tuple = (42) # This is just the integer 42!
# Without parentheses (tuple packing)
coordinates = 40.7128, -74.0060 # New York City lat/lng
# From a list
my_list = [1, 2, 3]
my_tuple = tuple(my_list)
# Named values β clean and readable
RGB_RED = (255, 0, 0)
RGB_GREEN = (0, 255, 0)
RGB_BLUE = (0, 0, 255)
print(f"Red color: R={RGB_RED[0]}, G={RGB_RED[1]}, B={RGB_RED[2]}")
πΉ Indexing & Slicing (same as lists)
months = ("Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec")
print(months[0]) # Jan
print(months[-1]) # Dec
print(months[3:6]) # ('Apr', 'May', 'Jun')
print(months[:3]) # ('Jan', 'Feb', 'Mar') β Q1
πΉ Tuple Unpacking β A Superpower
# Basic unpacking
x, y = (10, 20)
print(f"x={x}, y={y}")
# Swap variables without temp variable!
a, b = 5, 10
a, b = b, a
print(f"a={a}, b={b}") # a=10, b=5
# Extended unpacking with *
first, *rest = (1, 2, 3, 4, 5)
print(first) # 1
print(rest) # [2, 3, 4, 5]
*beginning, last = (10, 20, 30, 40)
print(beginning) # [10, 20, 30]
print(last) # 40
# Unpack from a function return
def get_user():
return ("Alice", 30, "alice@example.com")
name, age, email = get_user()
print(f"Name: {name}, Age: {age}, Email: {email}")
πΉ All Tuple Methods
Tuples only have 2 built-in methods (because theyβre immutable), but they support many built-in functions.
π count(item) β Count occurrences
lottery = (7, 14, 7, 3, 22, 7, 14)
print(lottery.count(7)) # 3
print(lottery.count(14)) # 2
print(lottery.count(99)) # 0 β no error if not found
π index(item) β Find first occurrence
colors = ("red", "green", "blue", "green", "yellow")
print(colors.index("green")) # 1 β first occurrence
print(colors.index("green", 2)) # 3 β search from index 2
try:
colors.index("purple")
except ValueError:
print("β 'purple' not found in tuple")
π Built-in Functions with Tuples
temperatures = (23.5, 19.0, 31.2, 25.8, 17.4, 29.6, 22.1)
print(f"Count: {len(temperatures)}") # 7
print(f"Max: {max(temperatures)}") # 31.2
print(f"Min: {min(temperatures)}") # 17.4
print(f"Sum: {sum(temperatures)}") # 168.6
print(f"Average: {sum(temperatures)/len(temperatures):.2f}") # 24.09
print(f"Sorted: {sorted(temperatures)}") # Returns a new list
# Check membership
print(23.5 in temperatures) # True
print(100 in temperatures) # False
π Converting Tuple β List
# Tuple to List (to modify it)
config = ("localhost", 8080, "production")
config_list = list(config)
config_list[1] = 9090 # Change port
config = tuple(config_list) # Convert back
print(config) # ('localhost', 9090, 'production')
# List to Tuple
servers = ["web-01", "web-02", "db-01"]
immutable_servers = tuple(servers)
print(immutable_servers) # ('web-01', 'web-02', 'db-01')
π Concatenation & Repetition
# Concatenation
t1 = (1, 2, 3)
t2 = (4, 5, 6)
combined = t1 + t2
print(combined) # (1, 2, 3, 4, 5, 6)
# Repetition
echo = ("Hello",) * 3
print(echo) # ('Hello', 'Hello', 'Hello')
separator = ("-",) * 20
print("".join(separator)) # --------------------
5. Sets β The Unique Collection
π A set is an unordered, mutable, and NO duplicates collection.
Perfect for: removing duplicates, membership testing, and mathematical set operations.
Syntax:my_set = {item1, item2, item3}
Creating Sets
# Basic set β duplicates are automatically removed!
numbers = {1, 2, 3, 2, 1, 4, 3}
print(numbers) # {1, 2, 3, 4} β Only unique values
# Empty set β MUST use set(), not {}
empty_set = set() # β
Correct
empty_dict = {} # β This creates an empty DICT, not a set!
# From a list (great for removing duplicates)
tags = ["python", "devops", "python", "linux", "devops", "git"]
unique_tags = set(tags)
print(unique_tags) # {'python', 'devops', 'linux', 'git'}
# From a string (unique characters)
chars = set("hello world")
print(chars) # {' ', 'd', 'e', 'h', 'l', 'o', 'r', 'w'}
πΉ All Set Methods β Complete Reference
β add(item) β Add a single item
permissions = {"read", "write"}
permissions.add("execute")
permissions.add("read") # Already exists β no duplicate added
print(permissions) # {'read', 'write', 'execute'}
β update(iterable) β Add multiple items
skills = {"python", "linux"}
skills.update(["docker", "kubernetes", "git"])
print(skills) # {'python', 'linux', 'docker', 'kubernetes', 'git'}
# Can accept multiple iterables
skills.update(["aws", "terraform"], {"ansible", "jenkins"})
print(skills)
β remove(item) β Remove item (raises error if not found)
fruits = {"apple", "banana", "cherry"}
fruits.remove("banana")
print(fruits) # {'apple', 'cherry'}
try:
fruits.remove("mango") # β Raises KeyError
except KeyError:
print("β 'mango' not in set")
β discard(item) β Remove item (NO error if not found)
fruits = {"apple", "banana", "cherry"}
fruits.discard("banana") # Removed β
fruits.discard("mango") # β
No error, just nothing happens
print(fruits) # {'apple', 'cherry'}
β pop() β Remove and return a random item
bag = {"pen", "pencil", "eraser", "ruler"}
item = bag.pop() # Removes a RANDOM item
print(f"Removed: {item}")
print(f"Remaining: {bag}")
β clear() β Remove ALL items
cache = {"key1", "key2", "key3"}
cache.clear()
print(cache) # set()
πΉ Set Mathematical Operations
This is where sets truly shine! π
π union() or | β All items from BOTH sets
python_devs = {"Alice", "Bob", "Charlie"}
java_devs = {"Bob", "Dave", "Eve"}
all_devs = python_devs.union(java_devs)
# Or: python_devs | java_devs
print(all_devs) # {'Alice', 'Bob', 'Charlie', 'Dave', 'Eve'}
π intersection() or & β Items in BOTH sets
python_devs = {"Alice", "Bob", "Charlie"}
java_devs = {"Bob", "Dave", "Charlie"}
both = python_devs.intersection(java_devs)
# Or: python_devs & java_devs
print(f"Know both languages: {both}") # {'Bob', 'Charlie'}
β difference() or - β Items in first set but NOT in second
all_employees = {"Alice", "Bob", "Charlie", "Dave", "Eve"}
on_vacation = {"Bob", "Eve"}
available = all_employees.difference(on_vacation)
# Or: all_employees - on_vacation
print(f"Available today: {available}") # {'Alice', 'Charlie', 'Dave'}
πΉ Real-World Set Examples
# Find duplicate entries in a log file
log_entries = ["192.168.1.1", "10.0.0.1", "192.168.1.1",
"172.16.0.1", "10.0.0.1", "192.168.1.1"]
unique_ips = set(log_entries)
duplicates = [ip for ip in log_entries if log_entries.count(ip) > 1]
unique_dups = set(duplicates)
print(f"Total entries: {len(log_entries)}") # 6
print(f"Unique IPs: {len(unique_ips)}") # 3
print(f"Duplicate IPs: {unique_dups}")
# β
Find common elements across datasets
users_viewed_page_a = {"user1", "user2", "user3", "user4", "user5"}
users_viewed_page_b = {"user3", "user4", "user5", "user6", "user7"}
users_purchased = {"user4", "user5", "user8"}
# Who saw page A AND B but didn't purchase?
saw_both = users_viewed_page_a & users_viewed_page_b
no_purchase = saw_both - users_purchased
print(f"Potential leads: {no_purchase}") # {'user3'}
# β
Quickly check if item exists (O(1) vs list O(n))
banned_words = {"spam", "phishing", "scam", "fraud"}
message = "This is a scam website"
for word in message.split():
if word.lower() in banned_words:
print(f"π¨ Banned word detected: '{word}'")
β
Use MATCH-CASE when:
β You have many specific value conditions to check
β Replacing long if/elif chains
β Matching against patterns, types, or structures
β
Use NESTED IF when:
β Decisions depend on the outcome of previous decisions
β Keep nesting β€ 3 levels for readability
β Consider extracting deep nesting into helper functions
β
Use LIST when:
β You need an ordered, changeable collection
β You need to add, remove, or sort items frequently
β You need duplicates
β
Use TUPLE when:
β Data should NOT change (coordinates, config, DB records)
β Returning multiple values from a function
β Keys in a dictionary (lists can't be dict keys!)
β
Use SET when:
β You need unique values only
β You need fast membership testing (x in set)
β You need mathematical set operations (union, intersection)
π Practice Challenge: Write a program that:
- Takes a list of student scores
- Uses match-case to assign grades
- Stores names in a tuple (immutable class roster)
- Uses a set to track which students passed
- Prints a summary using nested if for honors/standard/fail categories
Happy Coding! π β Your DevOps Teacher