elif
clausesWe've already seen that an if
statement
can optionally have an else
clause.
It can also optionally have any number of elif
clauses
— an abbreviation for “else if” —
preceding the else
clause.
A classic application where elif
is appropriate is in
translating a score into a letter grade.
if score >= 90:
grade = 'A'
elif score >= 80:
grade = 'B'
elif score >= 70:
grade = 'C'
elif score >= 60:
grade = 'D'
else:
grade = 'F'
The way this works is as follows: Upon encountering the
if
statement, the computer first checks the if
statement's condition, and if it passes, it does the body of the
if
clause (“grade = 'A'
”) and it is
done with the whole statement.
But if that condition fails, it proceeds to the next elif
clause's condition; if that succeeds, it does that elif
clause's condution and then is done with the whole statement.
But if it fails too, it proceeds to the next elif
clause's condition, going down until it finds the first
condition that is met; or, if they all fail, doing the else
clause's body (if it exists).
In this case, if score is 75, the first condition
“score >= 90
” fails,
and then the second condition
“score >= 80
” fails,
but the third condition
“score >= 70
” succeeds. So the body
“grade = 'C'
” is executed and we are done
with the statement.
While it happens to be true that the fourth condition
“score >= 60
” would also be successful, it
is never even noticed, because the computer stops upon the first
successful condition it finds.
Notice how the e's in elif
and else
all line up under the i in if
. This is
necessary for Python to recognize that they are all part of the
same statement.
Just as “x + 4
” is an expression
— that is, some Python code that is evaluated to be a value — so
is “x < 4
”. In the case of “x < 4
”,
the resulting value is not a number but a value that is either
true (if x
is below 4) or false.
Such a true/false value is called the Boolean type.
The Boolean type is most often used implicitly in
programs, so that you don't even think about it.
But it does occassionally show up explicitly. The following program —
to see if all words in a sentence start with the
letter p — is an example. Notice how it references
True
and False
— Python's way of writing
a true/false value directly into a program. (Oddly, True
and False
have to be capitalized.)
words = input().split()
all_ps = True
for w in words:
if w[0] != 'p':
all_ps = False
if all_ps:
print('All words start with p')
else:
print("Some words don't start with p")
To see this work, suppose the user types “peter piper picked a peck”.
w
:peter piper picked a peck all_ps
:True
False
It then reaches the final if
statement. Notice that the
if
statement has simply “all_ps
” as
its condition. This is entirely legitimate, because the if
is designed to take true/false values, and that is exactly what
all_ps
is. When the condition is true, we
execute the if
's body; and when it is false, we
execute the else
's body. In our example, all_ps
ends up False
, so the
By the way, this program works very differently if we change
the inner if
to:
if w[0] != 'p':
all_ps = False
else:
all_ps = True
In this case, the final word (peck) would
end up leading the else
clause to be executed, which
would set all_ps
back to True
. So the program
would incorrectly display “All words start with
p”.
and
, or
, not
Quite often we want to test multiple conditions on a line.
We can combine two conditions together using the and
operator. For example, suppose for some reason we want to test
whether a variable num
is both even and at least 100.
if num % 2 == 0 and num >= 100:
print('Number is large and even')
Technically, and
is an operator, like +
or ==
.
In this case, though, and
is built to take two Boolean
values and produce a Boolean value in response. If both are
true, the result is true.
We can also use the word or
as an operator.
if num % 2 == 0 or num >= 100:
print('Number is large or even')
In this case, we'll enter the if
if num
is
even or if num
is at least 100 — or if they both
are. So 24, 167, and 102 would all lead to “Number is
large or even” being displayed.
Like and
, or
is designed to deal with two
Boolean values. To our English-speaking brains, the following
makes perfect sense:
if num == 2 or 4:
print('Number is 2 or 4')
But Python interprets this as “(num == 2) or (4)
” — that is, or
is an operator whose
precedence level is lower than ==
, just as *
.
The second part — 4 — is true no matter what, so the
value of the overall or
is true regardless of
num
. So this little fragment always displays
“Number is 2 or 4”, even if num
is something
completely different, like 37.
So how should we write this? We need to make sure
“num ==
” appears after or
as well.
if num == 2 or num == 4:
print('Number is 2 or 4')
Going to back to our even/large example, what if we somehow
want to test whether a number is even or large, but not both?
We can do this using the not
operator, along with and
and or
.
if (num % 2 == 0 or num >= 100) and not (num % 2 == 0 and num >= 100):
print('Number is either large or even, but not both')
You'd want the parentheses here. Actually, Python does have
an order of operations among the Boolean operators: not
comes before and
, which comes before or
. But
many experienced programmers prefer to add parentheses to make
the order easier to understand. (In this case, the parentheses
are actually required to get the order we want.)
With and
, Python will evaluate the first part first.
If it turns out to be false, then there is no point in
evaluating the second part, and so Python won't even bother.
This is called short-circuit behavior.
Short-circuiting is often useful. For instance, suppose we
want to test whether the third letter of a word is the letter
z. Naturally, you might be tempted to write
“if word[2] == 'z':
” (remembering that
slot 2 holds the third letter, since the slots are numbered
starting from 0). However, when the word has only two letters,
word[2]
doesn't exist, and so Python would simply crash
the program. The solution is to test whether the word has at
least three letters before examining the third letter.
if len(word) >= 3 and word[2] == 'z':
If the word has only two letters, then the first condition will be false and so Python won't even bother with the second part — which is a good thing, because if it did, the program would crash. However, if the word does have three letters or more, it would go on to check the third letter.