Nested if Statements in Python
Learn how nested if, if-else, and if-elif-else statements work in Python, including indentation, execution flow, input validation, and logical alternatives.
A nested if statement is an if-based conditional located inside another conditional block. Nesting lets a program make a second decision only after a related first decision has been made.
For example, a program can first check whether a user is logged in and then, only for logged-in users, check whether the user has administrator permissions.
A conditional statement chooses which code to run based on whether a condition evaluates to the Boolean value True or False. An if statement runs its block when its condition is true; an else statement provides a fallback when the associated condition is false.
What Makes an If Statement Nested?
Nesting means placing one conditional statement inside the body of another conditional branch. The inner condition is relevant only after Python enters the outer branch that contains it.
is_logged_in = True
is_admin = False
if is_logged_in:
if is_admin:
print("Show administrator tools")
Python evaluates is_logged_in first. Only when that condition is true does Python evaluate is_admin.
This differs from two independent, sequential if statements:
if is_logged_in:
print("Show the account")
if is_admin:
print("Show administrator tools")
With independent statements, Python evaluates both conditions separately. With nesting, the inner check depends on reaching the outer block.
Basic Nested If Syntax
The general pattern has an outer if followed by an inner if that is indented one additional level.
if outer_condition:
if inner_condition:
action_when_both_are_true
Indentation defines Python's blocks. A block is a group of statements controlled by a header such as if, elif, or else. Use four spaces for each indentation level.
An inner else can be added inside the outer branch:
if outer_condition:
if inner_condition:
print("Both conditions are true")
else:
print("The outer condition is true, but the inner condition is false")
The inner conditional is skipped if outer_condition is false, because execution never enters its containing block.
Nested If-Else Syntax and Branch Association
A nested structure can have both an inner else and an outer else:
if outer_condition:
if inner_condition:
print("Outer true and inner true")
else:
print("Outer true and inner false")
else:
print("Outer false")
Each else belongs to the if at the same indentation level. The first else is indented to the same level as if inner_condition, so it belongs to the inner if. The second else aligns with if outer_condition, so it belongs to the outer if.
| Outer condition | Inner condition | Code path selected | Example classification |
|---|---|---|---|
| False | Not evaluated | Outer else | Not eligible |
| True | True | Inner if | Eligible and approved |
| True | False | Inner else | Eligible but not approved |
Indentation and Python Block Structure
Python uses leading whitespace to determine block membership instead of curly braces. Every statement controlled by a conditional header must be indented.
if account_exists: # level 0
if password_is_correct: # level 1
print("Signed in") # level 2
else: # level 1
print("Incorrect password")
else: # level 0
print("Account not found")
The inner if is one additional indentation level beneath the outer branch. Incorrect indentation can change which branch an else belongs to, change program behavior, or raise an IndentationError. Do not mix tabs and spaces; conventionally use four spaces per level.
Execution Flow in a Nested Decision
- Python evaluates the outer condition.
- If the outer condition is false, Python skips every statement in that outer
ifblock and runs the outerelse, if present. - If the outer condition is true, Python enters the block and evaluates the inner condition.
- Python runs either the inner
ifblock or the innerelseblock. - After the selected block finishes, execution continues after the complete nested structure.
For the pattern above, there are three practical routes: outer false; outer true and inner true; or outer true and inner false. There is no inner result on the first route because the inner condition was never evaluated.
Example: Minimum and Maximum Age Check
Suppose an age must be at least 18 and no greater than 65. The outer condition checks the minimum. Only qualifying ages receive the upper-bound check.
MINIMUM_AGE = 18
MAXIMUM_AGE = 65
try:
age = int(input("Enter your age: "))
if age < MINIMUM_AGE:
print("Below the minimum age")
else:
if age > MAXIMUM_AGE:
print("Above the maximum age")
else:
print("Age is in the accepted range")
except ValueError:
print("Please enter a whole number")
input() returns text, so int() converts valid numeric text to an integer before comparisons are performed. Text that is not a valid integer, such as "eighteen" or an empty string, causes int() to raise ValueError. The try-except block handles that invalid input.
| Representative input | Outer test | Inner test | Output category |
|---|---|---|---|
15 | False | Skipped | Below minimum |
30 | True | False | Accepted range |
70 | True | True | Above maximum |
This is a dependent check: the upper-bound test matters only after the minimum-age test succeeds.
Nested If Statements with Elif
elif means “else if.” It is an additional branch tested after a preceding if or elif condition is false. Use elif for mutually exclusive conditions at the same logical level.
An inner conditional can contain an if-elif-else chain:
has_ticket = True
seat_class = "business"
if has_ticket:
if seat_class == "first":
print("First-class seat")
elif seat_class == "business":
print("Business-class seat")
else:
print("Standard seat")
else:
print("Ticket required")
The outer conditional can also have elif branches:
status = "paused"
if status == "active":
print("Running")
elif status == "paused":
if has_ticket:
print("Paused with access")
else:
print("Paused without access")
elif status == "closed":
print("Closed")
else:
print("Unknown status")
More Than Two Levels of Nesting
An if can be placed inside another nested branch, creating three or more levels of control flow.
value = "42"
if value:
if value.isnumeric():
number = int(value)
if 1 <= number <= 100:
print("Valid value")
else:
print("Number is outside the allowed range")
else:
print("Value is not numeric")
else:
print("A value is required")
Each deeper condition adds another indentation level. This example validates presence, then numeric form, then range. Deeper nesting can express dependent validation, but excessive nesting makes control flow harder to read. Consider elif, logical operators, helper functions, or early returns when they make the intent clearer.
Logical Operators as an Alternative
A logical operator combines or reverses Boolean conditions. and requires both conditions to be true, or requires at least one to be true, and not inverts a Boolean result.
The accepted-age test can be flattened into a single inclusive range check:
age = int(input("Enter your age: "))
if 18 <= age <= 65:
print("Age is in the accepted range")
else:
print("Age is outside the accepted range")
The same logic can be written with and:
if age >= 18 and age <= 65:
print("Age is in the accepted range")
Nesting is useful when the second test genuinely depends on the first or when each stage needs a different response. A compound condition is often clearer when several related tests simply determine one result.
| Structure | Best use case | Example pattern | Readability note |
|---|---|---|---|
if | Run code for one condition | if ready: | Simple single decision |
if-else | Choose between two outcomes | if valid: ... else: ... | Exactly one branch runs |
if-elif-else | Choose among mutually exclusive same-level cases | if x == 1: ... elif x == 2: ... else: ... | Usually clearer than many separate if statements |
Nested if | Perform a dependent second check | if signed_in: if is_admin: | Shows staged decisions, but adds indentation |
| Compound condition | Combine related Boolean tests | if minimum <= value <= maximum: | Compact when the logic remains easy to understand |
Practical Dependent-Check Examples
Account Permissions
if is_logged_in:
if is_admin:
print("Administrator access granted")
else:
print("Signed in, but administrator access is not available")
else:
print("Please sign in first")
The authorization check occurs only after authentication succeeds.
Weather Activity
if is_raining:
if has_umbrella:
print("You can go outside with your umbrella")
else:
print("Choose an indoor activity")
else:
print("Choose an outdoor activity")
The umbrella check is relevant only when it is raining. When it is not raining, the outer else is selected and the inner check is skipped.
Common Mistakes
- Misaligned
else: Anelsebelongs to theifat the same indentation level. Align it with the intended conditional. - Incorrect indentation: Indent each block consistently by four spaces. Missing indentation or mixed tabs and spaces can raise
IndentationError. - Expecting the inner test to run after an outer false result: Nested code runs only after execution enters its enclosing block.
- Using separate
ifstatements for exclusive results: Separate statements can print multiple messages. Use anif-elif-elsechain or an appropriate nested structure when exactly one result should be selected. - Comparing input text with an integer:
input()returns a string. Convert numeric text withint()before numeric comparisons. - Ignoring invalid input:
int(input(...))can raiseValueError. Validate the input or handle the exception withtryandexcept. - Over-nesting: Many indentation levels can hide the main logic. Refactor with
elif,and/or, helper functions, or early returns where appropriate.
Troubleshooting Nested Conditionals
| Problem | Likely cause | Resolution |
|---|---|---|
The else branch runs unexpectedly | It is aligned with a different if than intended | Inspect indentation and align else with its associated if |
IndentationError | A block body is not indented, or tabs and spaces are mixed | Use consistent four-space indentation |
| The inner condition does not run | The outer condition evaluated to False | Test the outer condition with an input that enters its block |
TypeError during numeric comparison | The value from input() is still a string | Convert valid numeric text with int() |
ValueError after calling int() | The input was not numeric | Validate the text or catch ValueError |
| Several classification messages print | Independent if statements were used | Use mutually exclusive if-elif-else branches |
Summary
- A nested
ifplaces one conditional inside another conditional block. - Python evaluates the outer condition first and evaluates the inner condition only when its containing branch is reached.
- Indentation determines block membership and which
elsebelongs to whichif. - Use nesting for dependent, staged decisions such as authentication followed by authorization.
- Use
eliffor mutually exclusive conditions at the same logical level. - Use
and,or, andnotwhen a compound Boolean condition is clearer. - Convert numeric input with
int()and handle possibleValueErrorexceptions. - Refactor deeply nested code when a flatter structure improves readability.
For related syntax, review the Python if statement, if-else statements, if-elif statements, and logical operators. For input conversion, see getting user input and numeric variables.