Before we delve into the details of any of the concrete statements in Table 10-1, I want to begin our look at Python statement syntax by showing you what you are not going to type in Python code so you can compare and contrast it with other syntax models you might have seen in the past.
Consider the following if statement, coded in a C-like language:
if (x > y) {
x = 1;
y = 2;
}
This might be a statement in C, C++, Java, JavaScript, or similar. Now, look at the equivalent statement in the Python language:
if x > y:
x = 1
y = 2
The first thing that may pop out at you is that the equivalent Python statement is less, well, cluttered—that is, there are fewer syntactic components. This is by design; as a scripting language, one of Python’s goals is to make programmers’ lives easier by requiring less typing.
More specifically, when you compare the two syntax models, you’ll notice that Python adds one new thing to the mix, and that three items that are present in the C-like language are not present in Python code.
The one new syntax component in Python is the colon character (:). All Python compound statements—statements that have other statements nested inside them—follow the same general pattern of a header line terminated in a colon, followed by a nested block of code usually indented underneath the header line, like this:
Header line:
Nested statement block
The colon is required, and omitting it is probably the most common coding mistake among new Python programmers—it’s certainly one I’ve witnessed thousands of times in Python training classes I’ve taught. In fact, if you are new to Python, you’ll almost certainly forget the colon character very soon. You’ll get an error message if you do, and most Python-friendly editors make this mistake easy to spot. Including it eventually becomes an unconscious habit (so much so that you may start typing colons in your C-like language code, too, generating many entertaining error messages from that language’s compiler!).
Although Python requires the extra colon character, there are three things programmers in C-like languages must include that you don’t generally have to in Python.
The first of these is the set of parentheses around the tests at the top of the statement:
if (x < y)
The parentheses here are required by the syntax of many C-like languages. In Python, though, they are not—we simply omit the parentheses, and the statement works the same way:
if x < y
Technically speaking, because every expression can be enclosed in parentheses, including them will not hurt in this Python code, and they are not treated as an error if present.
But don’t do that: you’ll be wearing out your keyboard needlessly, and broadcasting to the world that you’re a programmer of a C-like language still learning Python (I know, because I was once, too). The “Python way” is to simply omit the parentheses in these kinds of statements altogether.
The second and more significant syntax component you won’t find in Python code is the semicolon. You don’t need to terminate statements with semicolons in Python the way you do in C-like languages:
x = 1;
In Python, the general rule is that the end of a line automatically terminates the statement that appears on that line. In other words, you can leave off the semicolons, and it works the same way:
x = 1
There are some ways to work around this rule, as you’ll see in a moment (for instance, wrapping code in a bracketed structure allows it to span lines). But, in general, you write one statement per line for the vast majority of Python code, and no semicolon is required.
Here, too, if you are pining for your C programming days (if such a state is possible) you can continue to use semicolons at the end of each statement—the language lets you get away with them if they are present, because the semicolon is also a separator when statements are combined.
But don’t do that either (really!). Again, doing so tells the world that you’re a programmer of a C-like language who still hasn’t quite made the switch to Python coding. The Pythonic style is to leave off the semicolons altogether. Judging from students in classes, this seems a tough habit for some veteran programmers to break. But you’ll get there; semicolons are useless noise in this role in Python.
The third and final syntax component that Python removes, and the one that may seem the most unusual to soon-to-be-ex-programmers of C-like languages (until they’ve used it for 10 minutes and realize it’s actually a feature), is that you do not type anything explicit in your code to syntactically mark the beginning and end of a nested block of code. You don’t need to include begin/end, then/endif, or braces around the nested block, as you do in C-like languages:
if (x > y) {
x = 1;
y = 2;
}
Instead, in Python, we consistently indent all the statements in a given single nested block the same distance to the right, and Python uses the statements’ physical indentation to determine where the block starts and stops:
if x > y:
x = 1
y = 2
By indentation, I mean the blank whitespace all the way to the left of the two nested statements here. Python doesn’t care how you indent (you may use either spaces or tabs), or how much you indent (you may use any number of spaces or tabs). In fact, the indentation of one nested block can be totally different from that of another. The syntax rule is only that for a given single nested block, all of its statements must be indented the same distance to the right. If this is not the case, you will get a syntax error, and your code will not run until you repair its indentation to be consistent.
The indentation rule may seem unusual at first glance to programmers accustomed to C-like languages, but it is a deliberate feature of Python, and it’s one of the main ways that Python almost forces programmers to produce uniform, regular, and readable code. It essentially means that you must line up your code vertically, in columns, according to its logical structure. The net effect is to make your code more consistent and readable (unlike much of the code written in C-like languages).
To put that more strongly, aligning your code according to its logical structure is a major part of making it readable, and thus reusable and maintainable, by yourself and others. In fact, even if you never use Python after reading this book, you should get into the habit of aligning your code for readability in any block-structured language. Python underscores the issue by making this a part of its syntax, but it’s an important thing to do in any programming language, and it has a huge impact on the usefulness of your code.
Your experience may vary, but when I was still doing development on a full-time basis, I was mostly paid to work on large old C++ programs that had been worked on by many programmers over the years. Almost invariably, each programmer had his or her own style for indenting code. For example, I’d often be asked to change a while loop coded in the C++ language that began like this:
while (x > 0) {
Before we even get into indentation, there are three or four ways that programmers can arrange these braces in a C-like language, and organizations often endure political battles and standards manuals to address the options (which seems more than a little off-topic for the problem to be solved by programming). Be that as it may, here’s the scenario I often encountered in C++ code. The first person who worked on the code indented the loop four spaces:
while (x > 0) {
--------;
--------;
That person eventually moved on to management, only to be replaced by someone who liked to indent further to the right:
while (x > 0) {
--------;
--------;
--------;
--------;
That person later moved on to other opportunities (ending that individual’s reign of coding terror...), and someone else picked up the code who liked to indent less:
while (x > 0) {
--------;
--------;
--------;
--------;
--------;
--------;
}
And so on. Eventually, the block is terminated by a closing brace (}), which of course makes this “block-structured code” (he says, sarcastically). No: in any block-structured language, Python or otherwise, if nested blocks are not indented consistently, they become very difficult for the reader to interpret, change, or reuse, because the code no longer visually reflects its logical meaning. Readability matters, and indentation is a major component of readability.
Here is another example that may have burned you in the past if you’ve done much programming in a C-like language. Consider the following statement in C:
if (x)
if (y)
statement1;
else
statement2;
Which if does the else here go with? Surprisingly, the else is paired with the nested if statement (if (y)) in C, even though it looks visually as though it is associated with the outer if (x). This is a classic pitfall in the C language, and it can lead to the reader completely misinterpreting the code and changing it incorrectly in ways that might not be uncovered until the Mars rover crashes into a giant rock!
This cannot happen in Python—because indentation is significant, the way the code looks is the way it will work. Consider an equivalent Python statement:
if x:
if y:
statement1
else:
statement2
In this example, the if that the else lines up with vertically is the one it is associated with logically (the outer if x). In a sense, Python is a WYSIWYG language—what you see is what you get—because the way code looks is the way it runs, regardless of who coded it.
If this still isn’t enough to underscore the benefits of Python’s syntax, here’s another anecdote. Early in my career, I worked at a successful company that developed systems software in the C language, where consistent indentation is not required. Even so, when we checked our code into source control at the end of the day, this company ran an automated script that analyzed the indentation used in the code. If the script noticed that we’d indented our code inconsistently, we received an automated email about it the next morning—and so did our managers!
The point is that even when a language doesn’t require it, good programmers know that consistent use of indentation has a huge impact on code readability and quality. The fact that Python promotes this to the level of syntax is seen by most as a feature of the language.
Also keep in mind that nearly every programmer-friendly text editor has built-in support for Python’s syntax model. In the IDLE Python GUI, for example, lines of code are automatically indented when you are typing a nested block; pressing the Backspace key backs up one level of indentation, and you can customize how far to the right IDLE indents statements in a nested block. There is no universal standard on this: four spaces or one tab per level is common, but it’s generally up to you to decide how and how much you wish to indent (unless you work at a company that’s endured politics and manuals to standardize this too). Indent further to the right for further nested blocks, and less to close the prior block.
As a rule of thumb, you probably shouldn’t mix tabs and spaces in the same block in Python, unless you do so consistently; use tabs or spaces in a given block, but not both (in fact, Python 3.X now issues an error for inconsistent use of tabs and spaces, as we’ll see in Chapter 12). Then again, you probably shouldn’t mix tabs or spaces in indentation in any structured language—such code can cause major readability issues if the next programmer has his or her editor set to display tabs differently than yours. C-like languages might let coders get away with this, but they shouldn’t: the result can be a mangled mess.
Regardless of which language you code in, you should be indenting consistently for readability. In fact, if you weren’t taught to do this earlier in your career, your teachers did you a disservice. Most programmers—especially those who must read others’ code—consider it a major asset that Python elevates this to the level of syntax. Moreover, generating tabs instead of braces is no more difficult in practice for tools that must output Python code. In general, if you do what you should be doing in a C-like language anyhow, but get rid of the braces, your code will satisfy Python’s syntax rules.
As mentioned previously, in Python’s syntax model:
The end of a line terminates the statement on that line (without semicolons).
Nested statements are blocked and associated by their physical indentation (without braces).
Those rules cover almost all Python code you’ll write or see in practice. However, Python also provides some special-purpose rules that allow customization of both statements and nested statement blocks. They’re not required and should be used sparingly, but programmers have found them useful in practice.
Although statements normally appear one per line, it is possible to squeeze more than one statement onto a single line in Python by separating them with semicolons:
a = 1; b = 2; print(a + b) # Three statements on one line
This is the only place in Python where semicolons are required: as statement separators. This only works, though, if the statements thus combined are not themselves compound statements. In other words, you can chain together only simple statements, like assignments, prints, and function calls. Compound statements like if tests and while loops must still appear on lines of their own (otherwise, you could squeeze an entire program onto one line, which probably would not make you very popular among your coworkers!).
The other special rule for statements is essentially the inverse: you can make a single statement span across multiple lines. To make this work, you simply have to enclose part of your statement in a bracketed pair—parentheses (()), square brackets ([]), or curly braces ({}). Any code enclosed in these constructs can cross multiple lines: your statement doesn’t end until Python reaches the line containing the closing part of the pair. For instance, to continue a list literal:
mylist = [1111,
2222,
3333]
Because the code is enclosed in a square brackets pair, Python simply drops down to the next line until it encounters the closing bracket. The curly braces surrounding dictionaries (as well as set literals and dictionary and set comprehensions in 3.X and 2.7) allow them to span lines this way too, and parentheses handle tuples, function calls, and expressions. The indentation of the continuation lines does not matter, though common sense dictates that the lines should be aligned somehow for readability.
Parentheses are the catchall device—because any expression can be wrapped in them, simply inserting a left parenthesis allows you to drop down to the next line and continue your statement:
X = (A + B +
C + D)
This technique works with compound statements, too, by the way. Anywhere you need to code a large expression, simply wrap it in parentheses to continue it on the next line:
if (A == 1 and
B == 2 and
C == 3):
print('spam' * 3)
An older rule also allows for continuation lines when the prior line ends in a backslash:
X = A + B + \
C + D # An error-prone older alternative
This alternative technique is dated, though, and is frowned on today because it’s difficult to notice and maintain the backslashes. It’s also fairly brittle and error-prone—there can be no spaces after the backslash, and accidentally omitting it can have unexpected effects if the next line is mistaken to be a new statement (in this example, “C + D” is a valid statement by itself if it’s not indented). This rule is also another throwback to the C language, where it is commonly used in “#define” macros; again, when in Pythonland, do as Pythonistas do, not as C programmers do.
As mentioned previously, statements in a nested block of code are normally associated by being indented the same amount to the right. As one special case here, the body of a compound statement can instead appear on the same line as the header in Python, after the colon:
if x > y: print(x)
This allows us to code single-line if statements, single-line while and for loops, and so on. Here again, though, this will work only if the body of the compound statement itself does not contain any compound statements. That is, only simple statements—assignments, prints, function calls, and the like—are allowed after the colon. Larger statements must still appear on lines by themselves. Extra parts of compound statements (such as the else part of an if, which we’ll meet in the next section) must also be on separate lines of their own. Compound statement bodies can also consist of multiple simple statements separated by semicolons, but this tends to be frowned upon.
In general, even though it’s not always required, if you keep all your statements on individual lines and always indent your nested blocks, your code will be easier to read and change in the future. Moreover, some code profiling and coverage tools may not be able to distinguish between multiple statements squeezed onto a single line or the header and body of a one-line compound statement. It is almost always to your advantage to keep things simple in Python. You can use the special-case exceptions to write Python code that’s hard to read, but it takes a lot of work, and there are probably better ways to spend your time.
To see a prime and common exception to one of these rules in action, however (the use of a single-line if statement to break out of a loop), and to introduce more of Python’s syntax, let’s move on to the next section and write some real code.