I l@ve RuBoard Previous Section Next Section

3.4 if Tests

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 ifs. 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).

3.4.1 General Format

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 elif's 
    <statements2>
else:                     # optional else
    <statements3>

3.4.2 Examples

Here are two simple examples of the if statement. All parts are optional except the initial if test and its associated statements. Here's the first:

>>> if 1:
...     print 'true'
...
true
>>> 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. The statement extends from the if line, through the else's block. Python executes the statements nested under the first test that is true, or else the else part. In practice, both the elif and else parts may be omitted, and there may be more than one statement nested in each section:

>>> 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!

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. Instead, multiway branching is coded as a series of if/elif tests as done above, or by indexing dictionaries or searching lists. Since dictionaries and lists can be built at runtime, they're sometimes more flexible than hardcoded logic:

>>> choice = 'ham'
>>> print {'spam':  1.25,           # a dictionary-based 'switch'
...        'ham':   1.99,           # use has_key() test for default case
...        'eggs':  0.99,
...        'bacon': 1.10}[choice]
1.99

An almost equivalent if statement might look like the following:

>>> 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

Dictionaries are good at associating values with keys, but what about more complicated actions you can code in if statements? We can't get into many details yet, but in Chapter 4, we'll see that dictionaries can also contain functions to represent more complex actions.

3.4.3 Python Syntax Rules

Since the if statement is our first compound statement, we need to say a few words about Python's syntax rules now. 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 we'll see in a moment, 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 as in C; rather, the end of a line marks the end of most statements.

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 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 in their own right.

S paces and comments are usually ignored

Spaces inside statements and expressions are almost always ignored (except in string constants and indentation). So are comments: they start with a # character (not inside a string constant) and extend to the end of the current line. Python also has support for something called documentation strings associated with objects, but we'll ignore these for the time being.

As we'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.[2]

[2] It's probably more novel if you're a C or Pascal programmer. Python's indentation-based syntax is actually based on the results of a usability study of nonprogrammers, conducted for the ABC language. Python's syntax is often called the "what you see is what you get" of languages; it enforces a consistent appearance that tends to aid readability and avoid common C and C++ errors.

3.4.3.1 B lock delimiters

As mentioned, block boundaries are detected by line indentation: all statements indented the same distance to the right belong to the same block of code, until that block is ended by a line less indented. Indentation can consist of any combination of spaces and tabs; 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). Blocks of code can be nested by indenting them further than the enclosing block. For instance, Figure 3.1 sketches the block structure of this example:

Figure 3.1. Nested code blocks
figs/lpy_0301.gif
x = 1
if x:
    y = 2
    if y:
        print 'block2'
    print 'block1'
print 'block0'

Notice that code in the outermost block must start in column 1, since it's unnested; nested blocks can start in any column, but multiples of 4 are a common indentation style. If this all sounds complicated, just code blocks as you would in C or Pascal, and omit the delimiters; consistently-indented code always satisfies Python's rules.

3.4.3.2 S tatement delimiters

As also mentioned, statements normally end at the end of the line they appear on, but when statements are too long to fit on a single line, a few special rules may be used:

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, parenthesized expressions and dictionary and list constants can span any number of lines. 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 (much like C #define macros). But since you can also continue by adding parentheses around long constructs, backslashes are almost never needed.

Other rules

Very long string constants can span lines arbitrarily. In fact, the triple-quoted string blocks in Chapter 2 are designed to do so. You can also terminate statements with a semicolon if you like (this is more useful when more than one statement appears on a line, as we'll see in a moment). Finally, comments can appear anywhere.

3.4.3.3 A few special cases

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 4), and so on. If you like using backslashes to continue you can, but it's more work, and not required:

if a == b and c == d and   \
   d == e and f == g:
   print 'olde'                  # backslashes allow continuations

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 simple statement (one without nested statements in it) on the same line, separated by semicolons. Some coders use this form to save program file real estate:

x = 1; y = 2; print x            # more than 1 simple statement

And finally, Python also lets you move a compound statement's body up to the header line, provided the body is just a simple statement. You'll usually 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. Six months down the road, you'll be happy you did.

3.4.4 Truth Tests Revisited

We introduced the notions of comparison, equality, and truth values in Chapter 2. 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:

The last item here is new; in short, Boolean operators are used to combine the results of other tests. There are three Boolean expression operators in Python:

X and Y

Is true if both X and Y are true

X or Y

Is true if either X or Y are true

not X

Is true if X is false (the expression returns 1 or 0)

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). Unlike C, Boolean operators are typed out as words in Python (instead of C's &&, ||, and !). Also unlike C, 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 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 (whether 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 evaluates and returns the object on the right (that may have a true or false value). and operations also 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 (whether true or false)
>>> [] and {} 
[]
>>> 3 and [] 
[]

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 (that happens to be false). The end result is the same as in C (true or false), but it's based on objects, not integer flags.[3]

[3] One common way to use Python Boolean operators is to select from one or more objects with an or; a statement such as X = A or B or C sets X to the first nonempty (true) object among A, B, and C. Short-circuit evaluation is important to understand, because expressions on the right of a Boolean operator might call functions that do much work or have side effects that won't happen if the short-circuit rule takes effect.

I l@ve RuBoard Previous Section Next Section