Python for Programmers: Blocks and Whitespace
Welcome to the Blocks and Whitespace lesson!
This lesson is shown as static text below. However, it's designed to be used interactively. Click the button below to start!
Most languages separate code blocks with {curly braces} or with keywords like
beginandend. Many languages require statement separators, like;. As we've seen, Python is different: code blocks are indicated with indentation, and we don't need to use statement separators. This lesson looks more closely at these unusual decisions in Python's design.Normally, Python statements are separated by newlines. However, we can also use
;to put multiple statements on a single line.>
x = 1; x += 2; x += 3xResult:
6
Although that works, it's unusual. Many Python style guides completely disallow
;.Some languages with {curly braces} allow them anywhere, not just on control constructs. For example, JavaScript lets us use curly braces to limit the scope of variables.
>
// This is JavaScript, not Python!
let temperature = 30
{
let multiplier = 2
temperature = temperature * multiplier
}
/* At this point, `temperature` is 60. But `multiplier` isn't defined at all
* because we're outside of the curly braces. */
multiplierResult:
We can imagine something similar in Python. Maybe we can indent code to scope variables like in the JavaScript code above.
>
temperature = 30multiplier = 2temperature *= multipliertemperatureResult:
It doesn't work: we can't use indentation to create new scopes. If we try to run the Python code above, we're probably making a mistake. Maybe we pasted the two indented lines from some other code, but didn't look at them closely. By disallowing code like this, Python forces us to pay more attention to code that we've copied and pasted.
Fortunately, Python's indentation rules are relatively simple. If a line is indented the same amount as the line before it, then it's part of the same block. If a line is indented more than the line before it, and the previous line has a
:(like afor ...:orif ...:) then it's starting a new block. If a line is indented less than the line before it, then it's outside of the previous line's block.Sometimes we want a single expression to span multiple lines in a file. Inside of open brackets (
(,[, or{), we can add as many newlines as we want, and we can add or remove indentation. One common example is function calls, where we sometimes put each argument on its own line for clarity.>
def multiply(a, b):return a * bmultiply(42,0)Result:
0
Any indentation is allowed in this situation, so Python will let us write terribly-formatted code.
>
def multiply(a, b):return a * bmultiply(42,0)Result:
0
There are two common ways to indent multi-line function calls, lists, etc. First, we can put continuations on their own line, always indenting them by the same amount.
>
def multiply(a, b):return a * bmultiply(42,0)Result:
0
Second, we can indent based on the column where the function call, parentheses, etc. started.
>
def multiply(a, b):return a * bmultiply(42,0)Result:
0
Both of those work equally well; it's a matter of preference.
There's one pitfall to keep in mind when adding newlines to an expression, like in the examples above. It's related to Python's literal string syntax. When two strings are adjacent in the code, with nothing between them, they're collapsed into a single string.
>
name = "Am" "ir"nameResult:
When spreading strings across multiple lines in a function call, list, etc., this can be very confusing. Let's say we have a list of sandwich ingredients.
>
ingredients = ["falafel","hummus","pickles"]We forgot to add pita, so we edit the list to add it. But we forget to add a comma after the existing
"pickles"element. Now the two strings are concatenated into a single list element.>
# Read closely here!ingredients = ["falafel","hummus","pickles""pita"]ingredients[2]Result:
'picklespita'
We can mitigate this problem by always including trailing commas at the end of each line in multi-line lists, dictionaries, etc., even on the last element.
>
ingredients = ["falafel","hummus","pickles",]If we always add that final comma, then we're less likely to accidentally concatenate two strings.
Finally, we can use
\to extend any line. The\doesn't do anything at runtime. It only tells Python that the next line is a continuation of the current line.>
large_value = 100 + \23large_valueResult:
123
It's unusual to use
\, but it does come in handy sometimes, especially when a project's style guide has a strict line length limit.