This chapter presents the Python if
statement—the main statement used for selecting from
alternative actions based on test results. Because this is our first
exposure to compound statements—statements
which embed other statements—we will also explore the general
concepts behind the Python statement syntax model here. And because
the if
statement introduces the notion of tests,
we’ll also use this chapter to study the concepts of
truth tests and Boolean expressions in general.
In simple terms, the Python
if
statement selects actions to perform.
It’s the primary selection tool in Python and
represents much of the logic a Python program
possesses. It’s also our first compound statement;
like all compound Python statements, the if
may
contain other statements, including other if
s. In
fact, Python lets you combine statements in a program both
sequentially (so that they execute one after another), and
arbitrarily nested (so that they execute only under certain
conditions).
The Python
if
statement is
typical of most procedural languages. It takes the form of an
if
test, followed by one or more optional
elif
tests (meaning
“else if”), and ends with an
optional
else
block. Each test and the else
have an associated
block of nested statements indented under a header line. When the
statement runs, Python executes the block of code associated with the
first test that evaluates to true, or the else
block if all tests prove false. The general form of an
if
looks like this:
if <test1>: # if test <statements1> # Associated block elif <test2>: # Optional elifs <statements2> else: # Optional else <statements3>
Let’s look at a few simple examples of
the
if
statement at
work. All parts are optional except the initial if
test and its associated statements; in the simplest case, the other
parts are omitted:
>>>if 1:
...print 'true'
... true
Notice how the prompt changes to " . . .
" for continuation lines in the basic interface used
here (in IDLE, you’ll simply drop down to an
indented line instead—hit Backspace to back up); a blank line
terminates and runs the entire statement. Remember that 1 is Boolean
true, so this statement’s test always succeeds; to
handle a false result, code the else
:
>>> if not 1:
... print 'true'
... else:
... print 'false'
...
false
Now, here’s an example of the most complex kind of
if
statement—with all its optional parts
present:
>>>x = 'killer rabbit'
>>>if x == 'roger':
...print "how's jessica?"
...elif x == 'bugs':
...print "what's up doc?"
...else:
...print 'Run away! Run away!'
... Run away! Run away!
This multiline statement extends from the if
line,
through the else
block. When run, Python executes
the statements nested under the first test that is true, or the
else
part if all tests are false (in this example,
they are). In practice, both the elif
and
else
parts may be omitted, and there may be more
than one statement nested in each section. Moreover, the words
if
, elif
, and
else
are associated by the fact that they line up
vertically, with the same indentation.
If you’ve used languages like C or Pascal, you might
be interested to know that there is no
“switch” or
“case” statement in Python that
selects an action based on a variable’s value.
Instead, multiway
branching
is coded as either a series of
if
/elif
tests as done in the
prior example, or by indexing dictionaries or searching lists. Since
dictionaries and lists can be built at runtime,
they’re sometimes more flexible than hardcoded
if
logic:
>>>choice = 'ham'
>>>print {'spam': 1.25, # A dictionary-based 'switch'
...'ham': 1.99, # Use has_key( ) or get( ) for default.
...'eggs': 0.99,
...'bacon': 1.10}[choice]
1.99
Although it usually takes a few moments for this to sink in the first
time you see it, this dictionary is a multiway branch—indexing
on key choice
branches to one of a set of values
much like a “switch” in C. An
almost equivalent and more verbose Python if
statement might look like this:
>>>if choice == 'spam':
...print 1.25
...elif choice == 'ham':
...print 1.99
...elif choice == 'eggs':
...print 0.99
...elif choice == 'bacon':
...print 1.10
...else:
...print 'Bad choice'
... 1.99
Notice the else
clause on the
if
here to handle the default
case when no key matches. As we saw in Chapter 6,
dictionary defaults can be coded with has_key
tests, get
method calls, or exception catching.
All of the same techniques can be used here to code a default action
in a dictionary-based multiway branch. Here’s the
get
scheme at work with defaults:
>>>branch = {'spam': 1.25,
...'ham': 1.99,
...'eggs': 0.99}
>>>print branch.get('spam', 'Bad choice')
1.25 >>>print branch.get('bacon', 'Bad choice')
Bad choice
Dictionaries are good at associating values with keys, but what about
more complicated actions you can code in if
statements? In Part IV, you’ll
learn that dictionaries can also contain
functions to represent more complex branch
actions, and implement general jump tables. Such functions appear as
dictionary values, are often coded as lambdas
, and
are called by adding
parenthesis to trigger their action.
In general, Python has a simple, statement-based syntax. But there are a few properties you need to know:
Statements
execute one after another, until you say otherwise. Python normally runs statements in a file or nested block from first
to last, but statements like the if
(and, as
you’ll see, loops) cause the interpreter to jump
around in your code. Because Python’s path through a
program is called the control flow, things like the
if
that affect it are called
control-flow
statements.
Block and statement boundaries are detected automatically. There are no braces or “begin/end” delimiters around blocks of code; instead, Python uses the indentation of statements under a header to group the statements in a nested block. Similarly, Python statements are not normally terminated with a semicolon; rather, the end of a line usually marks the end of the statements coded on that line.
Compound statements = header,
":
“,
indented statements. All
compound
statements in Python follow the same pattern: a header line
terminated with a colon, followed by one or more nested statements
usually indented under the header. The indented statements are called
a block (or sometimes, a suite). In the
if
statement, the elif
and
else
clauses are part of the
if
, but are header lines with nested blocks of
their own.
Blank lines, s
paces, and comments are usually ignored. Blank lines are ignored in files (but not at the interactive prompt).
Spaces inside statements and expressions are almost always ignored
(except in string literals and indentation). Comments are always
ignored: they start with a #
character (not inside
a string literal) and extend to the end of the current line.
Docstrings are ignored but saved, and displayed by tools. Python supports an additional comment form called documentation
strings (docstrings for short), which, unlike
#
comments, are retained. Docstrings are simply
strings that show up at the top of program files and some statements,
and are automatically associated with objects. Their contents are
ignored by Python, but they are automatically attached to objects at
runtime, and may be displayed with documentation tools. Docstrings
are part of Python’s larger documentation and are
covered at the end of Part III.
As you’ve seen, there are no variable type declarations in Python; this fact alone makes for a much simpler language syntax than what you may be used to. But for most new users, the lack of braces and semicolons to mark blocks and statements seems to be the most novel syntactic feature of Python, so let’s explore what this means in more detail here.
Python detects block boundaries automatically, by line indentation— the empty space to the left of your code. All statements indented the same distance to the right belong to the same block of code. In other words, the statements within a block line up vertically. The block ends at a line less indented or the end of the file, and more deeply nested blocks are simply indented further to the right than the statements in the enclosing block.
For instance, Figure 9-1 demonstrates the block structure of the following code:
x = 1 if x: y = 2 if y: print 'block2' print 'block1' print 'block0'
This code contains three blocks: the first (the top-level of the
file) is not indented at all; the second (within the outer
if
statement) is indented four spaces; and the
third (the print
statement under the nested
if
) is indented eight spaces.
In general, top-level (unnested) code must start in column 1. Nested blocks can start in any column; indentation may consist of any number of spaces and tabs, as long as it’s the same for all the statements in a given block. That is, Python doesn’t care how you indent your code; it only cares that it’s done consistently. Technically, tabs count for enough spaces to move the current column number up to a multiple of 8, but it’s usually not a good idea to mix tabs and spaces within a block—use one or the other.
Indentation to the left of your code is the only major place in Python where whitespace matters; in most other contexts, space can be coded or not. However, indentation is really part of Python syntax, not just a stylistic suggestion: all the statements within any given single block must be indented the same, or Python reports a syntax error. This is on purpose—because you don’t need to explicitly mark the start and end of a nested block of code, it removes some of the syntactic clutter found in other languages.
This syntax model also enforces indentation consistency, a crucial component of readability in structured programming languages like Python. Python’s syntax is sometimes called the “what you see is what you get” of languages—the indentation of code unambiguously tells readers what it is associated with. Python’s consistent appearance makes code easier to maintain.
Consistently-indented code always satisfies Python’s rules. Moreover, most text editors (including IDLE) make it easy to follow Python’s indentation model, by automatically indenting code as you type it.
Statements normally end at the end of the line they appear on. This covers the vast majority of the Python statements you’ll code. When statements are too long to fit on a single line, though, a few special rules may be used to make them span multiple continuation lines:
Statements may span lines if you’re continuing an
open syntactic pair. For statements that are too long to fit on one line, Python lets you
continue typing the statement on the next line, if
you’re coding something enclosed in (
)
, { }
, or [ ]
pairs.
For instance, expressions in parenthesis and dictionary and list
literals can span any number of lines; your statement
doesn’t end until the line on which you type the
closing part of the pair ( )
,
}
, or ]
). Continuation lines
can start at any indentation level.
Statements may span lines if they end in
a
backslash. This is a somewhat outdated feature, but if a statement needs to span
multiple lines, you can also add a backslash ()
at the end of the prior line to indicate you’re
continuing on the next line. But since you can also continue by
adding parentheses around long constructs, backslashes are almost
never needed.
Other rules. Very long string literals can span lines arbitrarily. In fact, the triple-quoted string blocks we met in Chapter 5 are designed to do so. Although uncommon, you can also terminate statements with a semicolon—this is sometimes used to squeeze more than one simple statement on a single line. Finally, comments and blank lines can appear anywhere.
Here’s what a continuation line looks like, using the open pairs rule; we can span delimited constructs across any number of lines:
L = ["Good", "Bad", "Ugly"] # Open pairs may span lines.
This works for anything in parentheses too: expressions, function arguments, functions headers (see Chapter 12), and so on. If you like using backslashes to continue you can, but it’s not usually necessary:
if a == b and c == d and d == e and f == g: print 'olde' # Backslashes allow continuations.
Because any expression can be enclosed in parenthesis, you can usually simply wrap something in parenthesis anytime you need to span multiple lines:
if (a == b and c == d and d == e and e == f): print 'new' # But parentheses usually do too.
As a special case, Python allows you to write more than one non-compound statement (i.e., statements without nested statements) on the same line, separated by semicolons. Some coders use this form to save program file real estate, but it usually makes for more readable code if you stick to one statement per line for most of your work:
x = 1; y = 2; print x # More than one simple statement
And finally, Python lets you move a compound
statement’s body up to the header line, provided the
body is just a simple (non-compound) statement.
You’ll see this most often used for simple
if
statements with a single test and action:
if 1: print 'hello' # Simple statement on header line
You can combine some of these special cases to write code that is difficult to read, but we don’t recommend it; as a rule of thumb, try to keep each statement on a line of its own, and indent all except the simplest of blocks. Six months down the road, you’ll be happy you did.
We introduced the notions of comparison, equality, and
truth values in Chapter 7. Since if
statements are
the first statement that actually uses test results,
we’ll expand on some of these ideas here. In
particular, Python’s Boolean operators are a bit different
from their counterparts in languages like C. In Python:
True means any nonzero number or nonempty object.
False means not true: a zero number, empty object, or
None
.
Comparisons and equality tests are applied recursively to data structures.
Comparisons and equality tests return 1 or 0 (true or false).
Boolean and
and or
operators
return a true or false operand object.
In short, Boolean operators are used to combine the results of other tests. There are three Boolean expression operators in Python:
Here, X
and Y
may be any truth
value or an expression that returns a truth value (e.g., an equality
test, range comparison, and so on). Boolean operators are typed out
as words in Python (instead of C’s
&&
, ||
, and
!
). Boolean and
and
or
operators return a true or false
object in Python, not an integer 1 or 0.
Let’s look at a few examples to see how this works:
>>> 2 < 3, 3 < 2 # Less-than: return 1 or 0
(1, 0)
Magnitude comparisons like these return an integer 1 or 0 as their
truth value result. But and
and
or
operators always return an object instead. For
or
tests, Python evaluates the operand objects
from left to right, and returns the first one that is true. Moreover,
Python stops at the first true operand it finds; this is usually
called
short-circuit
evaluation, since determining a result short-circuits
(terminates) the rest of the expression:
>>>2 or 3, 3 or 2 # Return left operand if true.
(2, 3)# Else return right operand (true or false).
>>>[ ] or 3
3 >>>[ ] or { }
{ }
In the first line above, both operands are true
(2
, 3
), so Python always stops
and returns the one on the left. In the other two tests, the left
operand is false, so Python simply evaluates and returns the object
on the right (which will happen to have a true or false value if
tested). Also, and
operations stop as soon as the
result is known; in this case, Python evaluates operands from left to
right and stops at the first false object:
>>>2 and 3, 3 and 2 # Return left operand if false.
(3, 2)# Else return right operand (true or false).
>>>[ ] and { }
[ ] >>>3 and [ ]
[ ]
Here, both operands are true in the first line, so Python evaluates
both sides and returns the object on the right. In the second test,
the left operand is false ([ ]
), so Python stops
and returns it as the test result. In the last test, the left side is
true (3
), so Python evaluates and returns the
object on the right (which happens to be a false [
]
).
The end result of all this is the same as in C and most other
languages—you get a value that is logically true of false, if
tested in an if
or while
.
However, in Python, Booleans return either the left or right object,
not an integer flag.
One final note: as described in Chapter 7, Python
2.3 includes a new Boolean type, named bool
, which
is internally a subclass of the int
integer type,
with values True
and False
.
These two instances are really just customized versions of integers
1
and 0
, which yield the words
True
and False
when printed or
otherwise converted to strings. The only time you’ll
generally notice this change is when you see Boolean outputs printed
as True
and False
. More on type
subclassing in Chapter 23.