5.3. Block structure¶
Many Python constructions are complex,
and can contain statements that have
expressions as parts. Consider,
for example, the Python if ... then
statement:
if verbose > 2:
print 'Temperature %s' % temperature
else:
print
This block of code says: If the value of the variable verbose is greater than 2, print out a message, otherwise just print a line break. The part of the statement between the if and the colon (:), is an expression that evaluates to True or False. (verbose > 2). Notice the second line is indented. Many programming languages use such indentation to make the flow of a program visually salient. The if/then statement creates a branching point in the program. On one branch one piece of code is executed. On the other, the other piece. Thus, the indentation helps keep the events on the two branches distinct. Usually the indentation is optional and what really matters is the presence of some kind of bracketing. For example in C++ the above would most likely be printed:
if (verbose > 2){
print 'Temperature %s' % temperature;}
else
{ print; }
One of the reasons this can be a problem is that different people use different conventions about combining indentation and brackets, making program branches difficult to follow. The unusual feature of Python is that the indentation is obligatory and the brackets are not allowed. That is, the indentation expresses the block structure. This takes some getting used to, and nearly everyone has a bad indentation experience early on, but it is not that hard to pick up, and it is quite effective at making programs more readable. It really helps the transition to use an editor that tries to do the indentation for you. For example the Canopy editor that comes with the free Enthought distribution of Python does this, as does Python mode in the Emacs editor (which is general purpose text editor), but Text Wrangler does not.
There are four basic places where blocks of code are introduced and indentation is obligatory:
Loop structures (for-loops, while loops)
if/then/else statements
Function and class definitions
The Python with construction (used for objects like IO streams with strict initialization and termination procedures).
Here are some examples:
if X > Y:
print Y
for elem in data:
print elem[0]
print elem[1]
def inc_abs_value (x):
if x >= 0:
inc = 1
else:
inc = -1
return x + inc
with open('pride_and_prejudice.txt','r') as fh:
file_contents = fh.read()
Notice the following uniformity: The code blocks are always
introduced by a colon (:). Everything in the code block must
then be uniformly indented. If a code block occurs inside another
code block, as in the definition of inc_abs_value
,
then the current level of indentation has to be increased.
The code block ends when the first
unindented line is reached and the unindented line must
start at some previously established indentation level,
as the return
statement does in the definition of inc_abs_value
.
Thus, compare the following versions of inc_abs_value
:
def inc_abs_value (x):
if x >= 0:
inc = 1
else:
inc = -1
return x + inc
def inc_abs_value (x):
if x >= 0:
inc = 1
else:
inc = -1
return x + inc
The first version returns a number whether x
is positive, 0,
or negative. The second version doesn’t return anything
when x
is non-negative (or, more accurately, it returns None
).
As noted above, unindented lines signal the end of a code block. Such line must start at some previously established indentation level. This, the following generates a Python syntax error:
if verbose > 2:
print 'Temperature %s' % temperature
print 'Continuing...'
else:
print
The problem is the line:
print 'Continuing...'
which unindents to an indentation level not previously used before. The error message looks like this:
File "example.py", line 3
print 'Continuing...'
^
IndentationError: unindent does not match any outer indentation level
The main question to ask yourself when you get an indentation error is “Did I indent where I shouldn’t, or did I miss an indentation where I needed one?” Sometimes, as in the example above, the error message makes it clear which kind of error you made.
The worst kind of indentation errors are the kinds that don’t raise an error message. Suppose that among the many millions of lines of code in your Star Wars Missile Defense system, you meant to include the following:
if bogie_confirmed():
if alert_level == NORMAL:
if check_that_bogie_one_more_time():
fire_missile()
elif alert_level > NORMAL:
fire_missile()
This says if the bogie’s confirmed then here’s what we do: If we have a normal alert level, let’s check one more time before firing the missile, but if the alert level is high, why let’s fire that big boy right away! But suppose due to a bad text editor, or a bad hair day, this gets indented a little wrong and we have instead:
if bogie_confirmed():
if alert_level == NORMAL:
if check_that_bogie_one_more_time():
fire_missile()
elif alert_level > NORMAL:
fire_missile()
Now assume the alert level is above NORMAL
.
What happens to Western (and Eastern) Civilization when
a bogie is confirmed? What about when a bogie is not
confirmed?
Here are some more examples
from the official Python docs.