Definition
A program that always runs the same lines in the same order can only ever do one thing. Yet as soon as it meets the real world, it runs into cases: a visitor who is logged in or anonymous, a cart that is empty or full, a file that is there or missing. It needs a way to say "this part of the code, only in this situation".
That is what if is for. This statement runs a block of code only when a condition is true, and skips it entirely otherwise. It is the simplest form of decision: the program picks its path from what it finds at the moment it runs, not from what was predictable at the moment you wrote it.
Here is the minimal form, three lines deciding whether a sentence is printed.
age = 20
# The condition is true, so the indented line runs
if age >= 18:
print("Adult")Two syntax details carry everything else. The condition ends with a colon, which announces the block to come, and that block is shifted to the right, by four spaces by convention.
That indentation is not decoration: it is the only thing telling Python where the conditional block starts and ends. What other languages wrap in braces, Python reads in the layout. The consequence is very concrete: a line you pull four spaces back to the left leaves the if and will run in every case, with no message to warn you.
That leaves the question everyone asks on meeting this form: what happens when the condition is false? Nothing, and that is precisely the point. The block is skipped, the program picks up at the first line back at the level of the if, and carries on. An if with nothing after it is perfectly valid: it forces you to write no branch at all for the opposite case.
Parentheses around the condition serve no purpose. if (age >= 18): works, because Python simply sees the parentheses of an ordinary expression, but nobody writes them. The habit comes from JavaScript, Java or C, where they are mandatory.
What Python treats as true
A condition does not have to be a comparison. Any value can be placed after if, and Python takes care of reducing it to true or false. Its rule is easy to remember: whatever is empty or zero is false, everything else is true.
The table below sums up the false side, the one worth knowing, since the other follows by elimination.
| Value tested | Result |
|---|---|
0, 0.0 | False |
| Empty string | False |
| Empty list, dictionary or set | False |
None | False |
| Everything else | True |
This rule explains a style you will meet in every Python project: if my_list:, which reads as "if the list holds something". It beats if len(my_list) > 0:, longer to write, longer to read, and saying nothing more.
The downside shows up as soon as the value tested could legitimately be zero. 0 and None are both false while telling very different stories: the first is an answer, the second the absence of one. When that distinction matters, do not lean on the general rule, and test explicitly with is None.
The mistake raises no exception, it produces a wrong result. A stock of 0, a score of 0, a 0 per cent discount: with if stock:, the code files all of those in the same branch as "no data at all", and the flaw only surfaces when a customer complains.
Chaining and closing
A lone if covers only two outcomes: the condition is true, or nothing happens. Most real decisions have more than that, and Python offers two words to write them.
elif adds another test, evaluated only when every test before it has failed. else closes the chain and picks up whatever no branch caught. A single branch runs, always the first one whose condition is true.
That brings a consequence which is easy to forget: the following tests are not merely ignored, they are never evaluated. The order in which you write the branches is therefore part of the logic, just as much as the conditions themselves.
The example below turns a score out of 20 into a grade. Watch the order of the thresholds as much as the thresholds themselves.
score = 14
# Python walks down the tests one by one and stops at the first true one
if score >= 16:
grade = "excellent"
elif score >= 14:
grade = "good"
elif score >= 12:
grade = "fair"
else:
grade = "pass"Follow Python through this example. It tries score >= 16, false with 14. It moves to the next test, score >= 14, which is true: it assigns "good", then leaves the chain. The third test and the else are not even looked at. Swap the first two branches and the same score comes out as "fair", without a single error being shown.
Finally, a decision sometimes exists only to pick a value, as it does here. Python then offers a condensed one-line form, the conditional expression: status = "adult" if age >= 18 else "minor". It earns its place when the choice fits in a few words, and turns unreadable the moment three cases are squeezed in.
Frequently asked questions
Why does Python have no switch statement?
For a long time the answer was that it did not need one: a chain of elif covers the same ground, and a dictionary makes an even clearer multi-way branch when the cases look alike. Since version 3.10 the match statement fills the gap, and adds pattern matching on top: it can take a tuple apart or recognise the shape of a dictionary, far beyond switching on a single value.
What is the difference between = and == in a condition?
A single sign assigns a value to a variable, a double one compares two values and returns a bool. Writing if x = 5: does not run at all and raises a SyntaxError, which is good news: in languages that allow assignment inside a test, the same typo yields a condition that is always true and a perfectly silent bug.
Can several conditions be combined in one if?
Yes, using and, or and not. Python evaluates them lazily: inside an and, if the first test is false the second never runs. That property is used to guard a risky access, as in if items and items[0], where the second part is only reached when the list holds at least one element.