Skip to main content

Flow Control

Introduction​

This chapter covers Python's conditional logic and iteration constructs: if/elif/else, the boolean operators and, or, and not, and the for/while loops. The running example throughout is date processing — validating a day, month, and year, and iterating over every date in a given month.

Python's remainder operator % is a useful tool for these kinds of problems. For example, a year is a leap year if it's evenly divisible by 4 and not evenly divisible by 100, or if it's evenly divisible by 400 — a classic use of % combined with and/or.


Concepts​

Boolean logic​

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

if / elif / else​

day, month, year = 29, 2, 2024

if month < 1 or month > 12:
print("Invalid month")
elif day < 1 or day > 31:
print("Invalid day")
else:
print(f"{day:02d}/{month:02d}/{year}")

for loops and range()​

for day in range(1, 32):
print(day)

while loops​

count = 0
while count < 5:
print(count)
count += 1

Examples​

def is_leap_year(year):
return (year % 4 == 0 and year % 100 != 0) or (year % 400 == 0)

def days_in_month(month, year):
days = [31, 29 if is_leap_year(year) else 28, 31, 30, 31, 30,
31, 31, 30, 31, 30, 31]
return days[month - 1]

year = 2016
month = 2

for day in range(1, days_in_month(month, year) + 1):
print(f"{day}/{month}/{year}")

Challenges​

1. Is it a leap year?​

  • Ask the user to enter a day, month, and year.
  • Determine whether the year is a leap year using the remainder operator, and print a message.
  • Test your logic against several known leap years and non-leap years (e.g. 2000, 1900, 2024, 2023).
💡 Show Answer
year = int(input("Enter a 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")

2. Validating a date​

  • Ask the user for a day, month, and year.
  • Validate that the month is between 1 and 12, the year is between 0 and 2099, and the day is valid for that month (taking leap years into account for February).
  • Print a single message saying whether the date is valid, in dd/mm/yyyy format.
💡 Show Answer
def is_leap_year(year):
return (year % 4 == 0 and year % 100 != 0) or (year % 400 == 0)

def days_in_month(month, year):
days = [31, 29 if is_leap_year(year) else 28, 31, 30, 31, 30,
31, 31, 30, 31, 30, 31]
return days[month - 1]

day = int(input("Enter the day: "))
month = int(input("Enter the month: "))
year = int(input("Enter the year: "))

if month < 1 or month > 12:
valid = False
elif year < 0 or year > 2099:
valid = False
elif day < 1 or day > days_in_month(month, year):
valid = False
else:
valid = True

date_str = f"{day:02d}/{month:02d}/{year:04d}"

if valid:
print(f"{date_str} is a valid date")
else:
print(f"{date_str} is not a valid date")

3. Listing all dates in a month​

  • Ask the user for a month and a year.
  • Print every date in that month, one per line, in d/m/yyyy format (taking leap years into account for February).
💡 Show Answer
def is_leap_year(year):
return (year % 4 == 0 and year % 100 != 0) or (year % 400 == 0)

def days_in_month(month, year):
days = [31, 29 if is_leap_year(year) else 28, 31, 30, 31, 30,
31, 31, 30, 31, 30, 31]
return days[month - 1]

month = int(input("Enter the month: "))
year = int(input("Enter the year: "))

for day in range(1, days_in_month(month, year) + 1):
print(f"{day}/{month}/{year}")

4. Verbose date output​

  • Extend the previous challenge so that dates are printed in a verbose format, e.g. 1 February 2016.
  • Add the correct ordinal suffix to the day number, e.g. 1st, 2nd, 3rd, 4th.
💡 Show Answer
MONTH_NAMES = ["January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December"]

def is_leap_year(year):
return (year % 4 == 0 and year % 100 != 0) or (year % 400 == 0)

def days_in_month(month, year):
days = [31, 29 if is_leap_year(year) else 28, 31, 30, 31, 30,
31, 31, 30, 31, 30, 31]
return days[month - 1]

def day_suffix(day):
if 11 <= day <= 13:
return "th"
return {1: "st", 2: "nd", 3: "rd"}.get(day % 10, "th")

month = int(input("Enter the month: "))
year = int(input("Enter the year: "))

for day in range(1, days_in_month(month, year) + 1):
print(f"{day}{day_suffix(day)} {MONTH_NAMES[month - 1]} {year}")