Exit slides Esc

Decisions

Slide 1 of 60

  1. A community calendar needs to decide whether the given year 2024 gets a leap day. The finished program should print one exact message:

    2024 is a leap year.

    How can a program choose the right message instead of printing every possibility?

  2. A leap year is divisible by 4, except a century year is not a leap year, except every 400th year is a leap year after all. That explains why 1900 is not a leap year, while 2000 and 2024 are leap years. In Python, the full test is (year % 4 == 0 and year % 100 != 0) or year % 400 == 0.

    Run the single given year below.

    Preview — you will build every part of this by the end of the unit.

  3. year = 2024
    is_leap_year = (year % 4 == 0 and year % 100 != 0) or year % 400 == 0
    
    if is_leap_year:
        print(f"{year} is a leap year.")
    else:
        print(f"{year} is not a leap year.")

    Output

    2024 is a leap year.
    

    The boolean test becomes True for 2024, so only the first indented message runs. We will build this payoff in three lessons. Each idea climbs the same ladder: minimal, one twist, then realistic.

    • Choose when code runs with if, elif, and else.

    • Combine yes-or-no tests with and, or, and not.

    • Put one decision inside another and order the branches so the right one runs.

  4. Lesson 1: Choose with if

    A one-way decision

    An if statement runs its indented block only when its condition is True. A colon ends the condition line.

    Minimal: print a message when a score reaches a target.

  5. score = 92
    
    if score >= 90:
        print("Target reached!")

    Output

    Target reached!
    

    The indented line belongs to the decision. It runs because 92 >= 90 is True.

    One twist: a false condition skips its block.

  6. temperature = 65
    
    if temperature > 80:
        print("Bring water.")
    
    print("Check complete.")

    Output

    Check complete.
    

    The indented reminder is skipped, but the unindented final line runs.

    Realistic: use an equality test to recognize an exact score. A common broken version uses assignment inside the condition.

  7. Error demo: this code stops with an error
    score = 90
    if score = 90:
        print("Exact score!")
  8. The traceback ends with SyntaxError because = saves a value; it does not ask an equality question. Use == in the condition.

  9. score = 90
    if score == 90:
        print("Exact score!")

    Output

    Exact score!
    

    if score == 90: asks a question and ends with a colon. The repaired program prints Exact score!.

  10. Two possible paths

    An else block supplies the path used when the if condition is False.

    Minimal: choose between two messages.

  11. has_ticket = True
    
    if has_ticket:
        print("Enter")
    else:
        print("Stop")

    Output

    Enter
    

    Exactly one branch runs: the if branch for True, or the else branch for False.

    One twist: the condition can compare a saved number.

  12. items = 7
    
    if items % 2 == 0:
        print("Even group")
    else:
        print("Odd group")

    Output

    Odd group
    

    The remainder decides which of the two labels is printed.

    Realistic: include the given value in the chosen output.

  13. balance = 12
    
    if balance >= 10:
        print(f"Balance {balance}: ready")
    else:
        print(f"Balance {balance}: add funds")

    Output

    Balance 12: ready
    

    Both branches use the same fixed value, but only the matching message appears.

  14. Real input: try the two-path score decision with a score supplied by a person.

  15. Try it
    score = int(input("Score: "))
    if score >= 10:
        print("Ready")
    else:
        print("Keep practicing")

    int() converts the typed score before the comparison, and only one message prints.

  16. Lesson 2: Choose among Several Paths

    Logical operators

    and is True only when both joined tests are true. or is True when at least one joined test is true. not reverses a boolean: True becomes False, and False becomes True.

    Minimal: join two booleans with and.

  17. print(True and False)

    Output

    False
    

    and prints False because both booleans must be True.

  18. One twist: use or so one true boolean is enough.

  19. print(True or False)

    Output

    True
    

    or prints True because its first boolean is True.

  20. Minimal: reverse one boolean.

  21. print(not True)

    Output

    False
    

    not True prints False because not flips the boolean.

    One twist: use not in a condition.

  22. has_ticket = False
    
    if not has_ticket:
        print("Ticket needed")

    Output

    Ticket needed
    

    has_ticket is False, so not has_ticket is True and the indented message runs.

    Another twist: check that a value is in an inclusive range.

  23. x = 7
    in_range = x >= 0 and x <= 10
    print(in_range)

    Output

    True
    

    x >= 0 and x <= 10 makes both boundary tests visible. The chained form 0 <= x <= 10 asks the same inclusive-range question.

  24. One twist: write the same inclusive range as a chained comparison.

  25. x = 7
    print(0 <= x <= 10)

    Output

    True
    

    The chained comparison prints True because 7 is between both endpoints.

  26. Realistic: accept either of two exact values.

  27. day = "Saturday"
    
    if day == "Saturday" or day == "Sunday":
        print("Weekend")
    else:
        print("Weekday")

    Output

    Weekend
    

    One true equality is enough for the or condition to choose Weekend.

  28. One twist: compare two strings that differ only in capitalization.

  29. print("Yes" == "yes")

    Output

    False
    

    Equality is case-sensitive, so "Yes" == "yes" prints False.

  30. Real input: try the weekend decision with a day supplied by a person.

  31. Try it
    day = input("Day: ")
    if day == "Saturday" or day == "Sunday":
        print("Weekend")
    else:
        print("Weekday")

    This cell asks for a day when you run it yourself; the decision still prints one label.

  32. elif runs top-down

    An elif adds another condition between if and else. Python checks the conditions from top to bottom, then runs the first matching branch and skips the rest.

    Minimal: classify a score with the highest threshold first.

  33. score = 95
    
    if score >= 90:
        print("Level A")
    elif score >= 80:
        print("Level B")
    else:
        print("Keep practicing")

    Output

    Level A
    

    95 also satisfies score >= 80, but the score >= 90 branch matches first. Python prints only Level A. Order matters.

    One twist: add another threshold while keeping the checks highest-to-lowest.

  34. score = 84
    
    if score >= 90:
        print("Gold")
    elif score >= 80:
        print("Silver")
    elif score >= 70:
        print("Bronze")
    else:
        print("Practice round")

    Output

    Silver
    

    84 misses the first test and matches the second, so later branches are not checked.

  35. One twist: an elif can require two tests at once with and.

  36. score = 84
    
    if score >= 90:
        print("Gold")
    elif score >= 80 and score < 90:
        print("Silver")
    else:
        print("Practice round")

    Output

    Silver
    

    Both parts of the elif are true for 84, so the Silver branch runs. The < 90 half is already guaranteed by the top-down order — it is written here only to show and inside an elif; in your own ladders, leave it out.

  37. Realistic: a triangle label must check the most specific equality pattern first.

  38. side_a = 5
    side_b = 5
    side_c = 5
    
    if side_a == side_b and side_b == side_c:
        print("Equilateral")
    elif side_a == side_b or side_a == side_c or side_b == side_c:
        print("Isosceles")
    else:
        print("Scalene")

    Output

    Equilateral
    

    An equilateral triangle also has pairs of equal sides. Checking equilateral first prevents the broader isosceles branch from taking it. The elif condition uses or: any one of its three equal-side tests is enough.

  39. Lesson 3: Build Clear Decision Trees

    Nested decisions

    A decision can contain another decision. The extra indentation shows that the inner question is asked only inside the chosen outer branch.

    Minimal: check permission before checking a score.

  40. has_permission = True
    score = 8
    
    if has_permission:
        if score >= 7:
            print("Activity unlocked")

    Output

    Activity unlocked
    

    The score test is reached only after permission is confirmed.

    One twist: give each decision its own alternative.

  41. has_permission = True
    score = 5
    
    if has_permission:
        if score >= 7:
            print("Activity unlocked")
        else:
            print("Raise the score")
    else:
        print("Permission needed")

    Output

    Raise the score
    

    Each else lines up with the condition it belongs to. Here permission is present, so the inner else prints.

    Realistic: use fixed stand-in text in a nested choice.

  42. age_text = "12"
    age = int(age_text)
    has_pass = True
    
    if age >= 10:
        if has_pass:
            print("Entry approved")
        else:
            print("Pass needed")
    else:
        print("Age requirement not met")

    Output

    Entry approved
    

    The fixed text "12" becomes an integer before the outer decision. Then the inner decision checks the pass.

  43. Real input: try the nested entry decision with an age supplied by a person.

  44. Try it
    age_text = input("Age: ")
    age = int(age_text)
    has_pass = True
    if age >= 10:
        if has_pass:
            print("Entry approved")
        else:
            print("Pass needed")
    else:
        print("Age requirement not met")

    The typed age becomes an integer before the outer decision; the inner decision runs only when the age qualifies.

  45. Return to the leap-year rule

    The calendar rule joins two paths: a year passes when it is divisible by 4 and not divisible by 100, or when it is divisible by 400. Parentheses keep the first pair together.

    Minimal: check whether one year is divisible by 4.

  46. year = 2024
    print(year % 4 == 0)

    Output

    True
    

    2024 has no remainder after division by 4, so the comparison prints True.

  47. One twist: exclude centuries from the divisible-by-4 rule.

  48. year = 2024
    print(year % 4 == 0 and year % 100 != 0)

    Output

    True
    

    Both tests are true for 2024, so this partial rule prints True.

  49. One twist: include years divisible by 400 again.

  50. year = 2024
    print((year % 4 == 0 and year % 100 != 0) or year % 400 == 0)

    Output

    True
    

    The complete rule prints True; the or adds the every-400th-year exception. When and and or share a condition, and binds tighter than or; use parentheses to show the intended groups.

  51. Minimal: save the boolean for one given year.

  52. year = 2024
    is_leap_year = (year % 4 == 0 and year % 100 != 0) or year % 400 == 0
    print(is_leap_year)

    Output

    True
    

    The full test prints True for the single given year 2024.

    One twist: use the saved boolean to choose one exact label.

  53. year = 2024
    is_leap_year = (year % 4 == 0 and year % 100 != 0) or year % 400 == 0
    
    if is_leap_year:
        label = "leap year"
    else:
        label = "common year"
    
    print(label)

    Output

    leap year
    

    The calculation and the message choice have separate jobs, which makes the rule easier to read.

    Realistic: print the full calendar message from the opening.

  54. year = 2024
    is_leap_year = (year % 4 == 0 and year % 100 != 0) or year % 400 == 0
    
    if is_leap_year:
        print(f"{year} is a leap year.")
    else:
        print(f"{year} is not a leap year.")

    Output

    2024 is a leap year.
    

    One condition controls two possible messages, and exactly one appears.

  55. Real input: try the full calendar decision with a year supplied by a person.

  56. Try it
    year = int(input("Year: "))
    is_leap_year = (year % 4 == 0 and year % 100 != 0) or year % 400 == 0
    if is_leap_year:
        print(f"{year} is a leap year.")
    else:
        print(f"{year} is not a leap year.")

    Converting the typed year lets the same full rule choose one calendar sentence.

  57. Final build

    Run the calendar decision with the fixed year 2024. Read the condition aloud: divisible by 4 and not by 100, or divisible by 400.

  58. # One given year; no repeated testing is needed.
    year = 2024
    is_leap_year = (year % 4 == 0 and year % 100 != 0) or year % 400 == 0
    
    if is_leap_year:
        print(f"{year} is a leap year.")
    else:
        print(f"{year} is not a leap year.")

    Output

    2024 is a leap year.
    

    Comparisons create booleans, logical operators combine them, and the decision selects the one matching output.

    • if runs a block when its condition is true.

    • elif checks another path; else handles what remains.

    • and, or, and not combine or reverse yes-or-no tests.

    • An indented decision inside another decision asks a second question.

    • Branch order matters because Python takes the first matching path.

    You can now build a calendar decision that identifies a leap year.