Leap Year Program in Python
Problem statement
Decide whether a given year is a leap year. The rule has three parts: divisible by 4 is a leap, unless it is divisible by 100, unless it is also divisible by 400.Approach 1: simple loop
Write the rule as nested if statements, one layer per clause. This mirrors the calendar rule exactly, which makes it easy to check line by line.
year = 2024
if year % 4 == 0:
if year % 100 == 0:
if year % 400 == 0:
print("Leap year")
else:
print("Not a leap year")
else:
print("Leap year")
else:
print("Not a leap year")
# Output: Leap yearThree questions in order: does 4 divide it? does 100 divide it? does 400 divide it? Each answer sends you one level deeper or straight to the output.
Approach 2: reusable function
The same rule compresses into one boolean expression. Putting it in a function keeps the formula testable — and it can be checked against known years in one line each.
def is_leap(year):
return year % 4 == 0 and (year % 100 != 0 or year % 400 == 0)
for y in [1900, 2000, 2024, 2023]:
print(y, is_leap(y))
# Output:
# 1900 False
# 2000 True
# 2024 True
# 2023 FalseRead the expression as the spoken rule: "divisible by 4, and either not divisible by 100 or divisible by 400." The parentheses are not decoration — they group the exception and its exception.
Approach 3: Pythonic alternative
The standard library already contains the rule — calendar.isleap() — and using it means the calendar authority, not your typing, is on the line.
import calendar print(calendar.isleap(2024)) # True print(calendar.isleap(1900)) # False
Know the manual version for exams and interviews; use this one in real projects.
Dry run
Trace 1900, the famous trap year. Divisible by 4? 1900 % 4 == 0 → yes, continue. Divisible by 100? 1900 % 100 == 0 → yes, continue deeper. Divisible by 400? 1900 % 400 is 300, not 0 → Not a leap year. Now trace 2000: the first two answers are the same, but 2000 % 400 == 0 → leap. The 4-100-400 ladder explains both results.
Common errors
- Stopping at the divisible-by-4 test — that alone calls 1900 a leap year, which it is not.
- Checking 400 before 100 in the nested version and scrambling the exception logic.
- Using
=instead of==in the conditions. - Forgetting the parentheses in the boolean form, which changes the grouping and the answer.
- Testing with only modern years — the bug lives in century years like 1700, 1800, 1900, 2100.
Practice on PyDebug
Turn the idea into a debugging habit with these free browser exercises: