Operators
A logical operator joins or reverses conditions. In Python the three logical operators are written as and, or and not, all in lower case.
Written out in an algorithm, the operators appear as AND, OR and NOT. Python keywords are case-sensitive, so AND is not the same as and: typing the upper-case spelling stops the program with a syntax error rather than combining your conditions.
| In an algorithm | In Python 3 |
|---|---|
| AND | and |
| OR | or |
| NOT | not |
Every condition is a Boolean expression: Python evaluates it to either True or False. These are the two Boolean values, and they always begin with capital letters. A comparison such as height >= 140 is a Boolean expression. Equality uses two equals signs: score == 10 compares two values, while score = 10 assigns a value to a variable.
The operands of and, or and not can be comparisons or Boolean variables. If has_wristband and is_member already hold True or False, then has_wristband and is_member is a Boolean expression too. not reverses a single operand, so not is_member is True when is_member is False.
The result can be stored in a Boolean variable, or used directly as a condition. In the example, can_climb stores the combined result, and not can_climb is the condition the if tests.
height = 152
has_wristband = True
is_member = False
is_tall_enough = height >= 140
can_climb = is_member or (has_wristband and is_tall_enough)
print("Climb allowed: " + str(can_climb))
if not can_climb:
print("Ask an instructor")Output:
Climb allowed: TrueA logic error is a mistake where a program runs but the result is wrong. Choosing and when you need or (or the other way round) causes one, because the condition is still valid Python — nothing crashes, but the test gives the wrong answer for some inputs, so the rule you meant is broken.
To correct the condition, put the rule into words first, then ask how many parts must be true. If every part has to be true, join the tests with and. If any single part being true is enough, join them with or.
A pool stays open if the water is warm and a lifeguard is on duty, because both have to hold. A machine stops if the guard is opened or the stop button is pressed, because either one alone must halt it.
Validation catches people out because the same two limits can be written in two ways. A value inside a valid range must be above the lower limit and below the upper limit. A value outside the range is invalid as soon as it is below the lower limit or above the upper limit.
| What you are testing | Condition for limits 2 and 8 | Operator |
|---|---|---|
| Value is inside the range (valid) | players >= 2 and players <= 8 | and |
| Value is outside the range (invalid) | players < 2 or players > 8 | or |
A bowling alley takes bookings for 2 to 8 people. The test players < 2 or players > 8 rejects a party of 1 because the first comparison is true, and a party of 10 because the second is, and one true comparison is enough. Change that or to and and you are asking for a number below 2 and above 8 at the same time, which nothing can be, so the message never appears even though the program runs happily.
players = int(input("How many players? "))
if players < 2 or players > 8:
print("Sorry, bookings are for 2 to 8 people")
else:
print("Lane booked")Output when the user types 10:
How many players? 10
Sorry, bookings are for 2 to 8 peopleWork out the rule in words first, then pick the operator to match it — that is what puts the logic error right.
A logical expression is a condition built from two or more comparisons joined with and or or, or a single comparison reversed with not. It works out to a single True or False, so it can go straight into the condition of an if, elif or while statement. Nothing extra is needed around it: the expression is the condition.
Imagine a climbing wall that accepts you only if you are at least 12 and you have handed in a consent form. One way is a second if inside the first, asking about the form. Joining both comparisons with and does the same job in one condition, which is shorter and less likely to go wrong. The elif line below repeats the idea: its expression is tested only when the first condition was False.
age = int(input("Age: "))
consent = input("Consent form handed in? yes or no: ")
if age >= 12 and consent == "yes":
print("You can climb")
elif age >= 12 and consent != "yes":
print("Hand in your consent form first")
else:
print("Sorry, you are too young")Output when the user types 12, yes:
Age: 12
Consent form handed in? yes or no: yes
You can climb
An or expression is True when at least one comparison is True, so it suits a decision where either event is enough. This game ends when the score reaches 100 or the player has no lives left.
score = int(input("Score: "))
lives = int(input("Lives left: "))
if score >= 100 or lives == 0:
print("Game over")
else:
print("Keep playing")Output when the user types 120, 2:
Score: 120
Lives left: 2
Game over
A condition finishes at the colon, and the indented lines below it run when the condition is True. Indenting a line that should sit outside the decision makes the computer treat it as part of the decision, and leaving out indentation where it is needed causes an error. Correct logic can still misbehave if a statement lands in the wrong block.
A while loop tests its condition before each repeat, so a logical expression there decides whether the loop runs again. A practice game might repeat while the timer is above zero and the goals scored is below five: the loop stops as soon as either part becomes False, so it ends when time runs out or the target is reached. Swap in or and it carries on while at least one part is True, stopping only when both are False. A not reverses a test, so a loop can keep running until that event happens.
| Loop condition | Repeats while | Stops when |
|---|---|---|
timer is above 0 and goals is below 5 | both comparisons are True | either comparison becomes False |
timer is above 0 or goals is below 5 | at least one comparison is True | both comparisons are False |
A compound condition combines more than one comparison, joining them with and or or, or reversing one with not. You work out each test and the operator beside it together, so the way you lay the condition out decides whether another programmer, or you next week, can see the intended logic straight away.
Logical operators let one condition replace a stack of nested if statements, which makes a program shorter and easier to follow. That only works while the condition stays readable. A long condition with several and and or parts crammed onto one line hides the grouping, so the reader has to work out the order in their head. It still runs, but it is much easier to end up with a logic error — a test that is written wrongly and so checks the wrong thing. Bracketing the groups, or splitting the logic into two shorter conditions, keeps the meaning in plain sight.
# Cinema discount: a teenager with enough card points
age = int(input("Enter your age: "))
points = int(input("Enter your card points: "))
if (age >= 13) and (age <= 19) and (points > 50):
print("Half price ticket")
else:
print("Full price ticket")Output when the user types 15, 80:
Enter your age: 15
Enter your card points: 80
Half price ticket
Every part of the condition above is bracketed and spaced out, so you can see at once that all three tests have to be true together for the discount to apply.