Combining Conditions
Real decisions rarely hang on a single question. A cinema gives a discount to children or to people over 65. A form is complete only if the name is filled in and the email is too. Python joins simple comparisons into rules like these with three words, and, or and not, and it adds two conveniences: almost any value can stand in for True or False, and a special value, None, stands for "nothing at all".
Picture a club door with rules written on a board: over 18 and holding a ticket, or on the guest list. The person at the door applies the words exactly as written, no more and no less. Python does the same, which is mostly what you want and occasionally a surprise.
and, or, not
and is True only when both sides are True. or is True when at least one side is. not turns True into False and False into True. The table in the figure lists every combination; there are only four for each word.
In the program below, a child of 12 gets the discount because the first half of the or is True. A person of 40 does not, because neither half is.
for age in [12, 40, 70]: if age < 18 or age >= 65: print(age, "gets the discount") else: print(age, "pays full price")
12 gets the discount 40 pays full price 70 gets the discount
Notice that print is given two values separated by a comma; it prints them on one line with a space between. The first line of that program repeats the check for three ages, one after another. That is a loop, which Chapter 4 teaches; for now it is enough that the indented lines run once for each age in the list.
| A | B | A and B | A or B |
|---|---|---|---|
| True | True | True | True |
| True | False | False | True |
| False | True | False | True |
| False | False | False | False |
Ranges, the Readable Way
To check that a value lies between two limits, Python lets you chain comparisons the way you would on paper. 18 <= age < 65 means age is at least 18 and below 65. It is exactly the same as two comparisons joined by and, just easier to read.
>>> age = 30 >>> 18 <= age < 65 True
The Classic Trap: or with a Bare Value
Here is a mistake almost every beginner makes once. The program below means "if the day is Saturday or the day is Sunday". But the day is Monday, and it still prints that it is the weekend.
day = "Monday" if day == "Saturday" or "Sunday": print("Weekend!")
Weekend!
Python read the condition as two separate questions joined by or: is day equal to Saturday, which is False, or is the text Sunday true, which, as the next section explains, it always is. The fix is to write the comparison out on both sides: day equals Saturday, or day equals Sunday.
day = "Monday" if day == "Saturday" or day == "Sunday": print("Weekend!") else: print("A working day.")
A working day.
What Counts as True
Any value can be used where Python expects True or False. A small set of values count as false: the number 0, the empty string, an empty list, and None. Almost everything else counts as true, including any non-empty text such as the word Sunday. That is why the trap above always fired.
This lets you write short checks such as if name:, which reads as "if a name was given". It is a convenience with one sharp edge, flagged here because it bites: an amount of zero counts as false, so if amount: treats a real amount of 0 the same as a missing one.
name = "" if name: print("Hello,", name) else: print("No name given")
No name given
None: the Value That Means Nothing Yet
None is Python's value for "no value here yet": a discount that has not been decided, a search that found nothing. It is not zero and it is not empty text; it is a different thing entirely. To ask whether a name points at it, use is None, which reads almost like English.
>>> discount = None >>> discount is None True >>> discount == 0 False
- "
if day == "Saturday" or "Sunday":checks both days." It checks whether day is Saturday, or whether the text Sunday is true, which it always is. Write the comparison on both sides of or. - "An empty string is None." Empty text is still text. None is the absence of any value, and
"" is Noneis False. - "not applies to the whole line." not reverses the condition right after it, up to the next and or or:
not a > 5 and bmeans (not a > 5) and b. When in doubt, add brackets to make the grouping visible. - "
if amount:checks whether an amount was given." It also treats a real amount of zero as missing. When zero is a valid value, compare withis Noneinstead.
- Most rules in real software are two or three conditions joined together; now they can be written the way they are spoken.
- The or-with-a-bare-value trap is one of the most common bugs in beginner code, and recognising it saves real hours.
Knowledge Check
When is a and b True?
- When at least one of a or b happens to be True at the time
- Only when both a and b are True at the same time
- When a is True, whatever the value of b turns out to be
- When a and b have the same value, both True or both False
With day = "Monday", what does day == "Saturday" or "Sunday" count as?
- False, because Monday is neither Saturday nor Sunday
- An error, because or cannot be followed by text
- True, because the non-empty text Sunday counts as true
- Monday, because or gives back the value it compared
Which of these values counts as false in an if?
- The text
"0", because it contains a zero - The text
"False", because it spells out the word - The number -1, because it is less than zero and negative
- An empty string, with nothing between the quotes
What is None?
- A value meaning that no value has been set yet
- Another way of writing the number zero in Python
- An empty string, written without any quotes
- An error that Python raises when a name is missing
You got correct