What’s one thing you learned? What’s still confusing?
Error Handling & Debugging: Don't Panic at Red Text
Read Python errors confidently, handle failures with try/except, and debug systematically.
Mini-Project: Robust Calculator
Build a calculator that survives any bad input using try/except and validation loops.
File I/O: Read, Write & Persist Data
Open files with `with`, handle errors gracefully, and work with pathlib, json, and csv.
Interactive Labs for This Track
Loop Visualizer
You're a factory robot repeating the same task on an assembly line — watch how loops automate repetitive work
List Slicing
You have a playlist of 50 songs — grab just tracks 10 through 20 with a single slice expression
Sorting Algorithms
You're organizing a library of 10,000 books — which sorting method is fastest?
Ask questions, share insights
any() with generator expressions, and the rule-collection pattern used by real validators everywhere.weak, medium, or strong) along with a list of human-friendly hints for what's missing.Enter a password: hello
Strength: weak
Missing:
- at least 8 characters
- an uppercase letter
- a digit
- a special character
Enter a password: Hunter2!
Strength: strong
No issues. Good to go.
len(), .isupper(), .isdigit(), etc.any() with a generator expression for "does this contain at least one X?"len(password) >= 8 is a True/False expression you can use directly.def is_long_enough(password):
return len(password) >= 8
print(is_long_enough("hi")) # False
print(is_long_enough("Hunter2!")) # TrueTiny function, big habit -- one rule per function, each returning a boolean. That's the structure every validator in production uses.
What does "Hello".isupper() return?
.isupper() returns True only when ALL the alphabetic characters in the string are uppercase. "Hello" has lowercase letters (e, l, l, o), so it's False. Common misconception: thinking it checks if the string CONTAINS any uppercase. To check that, you need any(c.isupper() for c in s). Same pattern applies to .islower(), .isdigit(), .isalpha() — they all check "is ALL of it this kind?", not "does it contain?".What does `len('Hunter2!')` return?
'A'.isupper() returns True. But how do you check the whole password for "contains AT LEAST ONE uppercase letter"? Use any() with a generator expression.def has_upper(password):
return any(c.isupper() for c in password)
print(has_upper("hello")) # False
print(has_upper("Hello")) # Trueany(...) returns True if at least one item in the iterable is truthy. The generator expression c.isupper() for c in password yields True/False for each character. As soon as one True is found, any() short-circuits and returns True.What does any([]) return?
any() on an empty iterable returns False — because there's nothing truthy in there. Symmetric oddity: all([]) returns True (no falsy item exists). This is logical: "any element is truthy" requires at least one element; "all elements are truthy" is vacuously satisfied with zero elements. This matters when validating: any(c.isupper() for c in "") returns False, correctly rejecting empty passwords.What does `any(c.isdigit() for c in 'abc')` return?
any pattern for digits, lowercase, and special characters. Special characters are anything not alphanumeric -- the easiest check is not c.isalnum().def check_password(password):
rules = {
"at least 8 characters": len(password) >= 8,
"an uppercase letter": any(c.isupper() for c in password),
"a lowercase letter": any(c.islower() for c in password),
"a digit": any(c.isdigit() for c in password),
"a special character": any(not c.isalnum() for c in password),
}
return rules
print(check_password("Hunter2!"))
# {'at least 8 characters': True, 'an uppercase letter': True, ...}The dict maps "human description" to "rule passes?". Now you can ask: how many rules pass? Which ones failed?
Count the rules that pass. Use that count to assign a strength label.
def strength(password):
rules = check_password(password)
score = sum(rules.values()) # True is 1, False is 0
if score <= 2:
return "weak"
if score == 3 or score == 4:
return "medium"
return "strong"
print(strength("hi")) # weak
print(strength("Hello12")) # medium
print(strength("Hunter2!")) # strongsum(rules.values()) works because Python treats True as 1 and False as 0 in arithmetic. Then a simple ladder maps the score to a label.What does this print? flags = [True, False, True, True, False] print(sum(flags))
True is literally 1 and False is literally 0 for arithmetic purposes (bool is a subclass of int). So sum([True, False, True, True, False]) is 1 + 0 + 1 + 1 + 0 = 3. This is hugely useful: any time you want to COUNT how many things are true, sum(condition for item in items) is the Pythonic way. Examples: sum(score >= 60 for score in grades) counts passing grades, sum(c.isupper() for c in s) counts uppercase letters.The point of a strength meter is to help the user fix it. Return the list of rules that DIDN'T pass.
def feedback(password):
rules = check_password(password)
missing = [name for name, passed in rules.items() if not passed]
label = strength(password)
return label, missing
label, missing = feedback("hello")
print("Strength:", label)
if missing:
print("Missing:")
for item in missing:
print(f"- {item}")
else:
print("No issues. Good to go.")That's the entire meter -- six small functions, each doing one thing, composed into a real user-facing tool.
Write `strength_report(password)` that returns a tuple (label, missing_list) where label is 'weak'/'medium'/'strong' and missing_list is a list of human-readable strings naming the rules that failed. Use 5 rules: length >= 8, has upper, has lower, has digit, has special character (anything not alphanumeric). Score: 0-2 rules = weak, 3-4 = medium, 5 = strong.
Enter a password: hello
Strength: weak
Missing:
- at least 8 characters
- an uppercase letter
- a digit
- a special character
Enter a password: Hunter2!
Strength: strong
No issues. Good to go.This code calls input(). Python here can't pause to ask you, so type the answers below before running — one value per line, in the order the program asks for them.
def strength_report(password):
rules = {
# TODO: 5 rules mapping description -> True/False
}
score = sum(rules.values())
# TODO: assign label based on score
# TODO: build missing list
return label, missing
def main():
while True:
password = input("Enter a password: ")
if not password:
break
label, missing = strength_report(password)
print(f"Strength: {label}")
if missing:
print("Missing:")
for item in missing:
print(f"- {item}")
else:
print("No issues. Good to go.")
print()
main()
Try one of these variations:
import math; bits = len(password) * math.log2(charset_size). Print "Estimated time to crack: ..." based on entropy bands.try/except so your code survives bad input instead of crashing.