The Python Apprentice

4.5 (6 reviews total)
By Robert Smallshire , Austin Bingham
    What do you get with a Packt Subscription?

  • Instant access to this title and 7,500+ eBooks & Videos
  • Constantly updated with 100+ new titles each month
  • Breadth and depth in over 1,000+ technologies
  1. Getting started

About this book

Experienced programmers want to know how to enhance their craft and we want to help them start as apprentices with Python. We know that before mastering Python you need to learn the culture and the tools to become a productive member of any Python project. Our goal with this book is to give you a practical and thorough introduction to Python programming, providing you with the insight and technical craftsmanship you need to be a productive member of any Python project. Python is a big language, and it’s not our intention with this book to cover everything there is to know. We just want to make sure that you, as the developer, know the tools, basic idioms and of course the ins and outs of the language, the standard library and other modules to be able to jump into most projects.

Publication date:
June 2017


Chapter 1. Getting started

In this chapter we'll cover obtaining and installing Python on your system for Windows, Ubuntu Linux, and macOS. We'll also write our first basic Python code and become a acquainted with the essentials Python programming culture, such as the Zen of Python, while never forgetting the comical origins of the name of the language.


Obtaining and installing Python 3

There are two major versions of the Python language, Python 2 which is the widely deployed legacy language and Python 3 which is the present and future of the language. Much Python code will work without modification between the last version of Python 2 (which is Python 2.7 ( and recent versions of Python 3, such as Python 3.5 ( However, there are some key differences between the major versions, and in a strict sense the languages are incompatible. We'll be using Python 3.5 for this book, but we'll point out key differences with Python 2 as we go. It's also very likely that, this being a book on Python fundamentals, everything we present will apply to future versions of Python 3, so don't be afraid to try those as they become available.

Before we can start programming in Python we need to get hold of a Python environment. Python is a highly portable language and is available on all major operating systems. You will be able to work through this book on Windows, Mac or Linux, and the only major section where we diverge into platform specifics is coming right up — as we install Python 3. As we cover the three platforms, feel free to skip over the sections which aren’t relevant for you.


The following are the steps to be performed for Windows platform:

  1. For Windows you need to visit the official Python website, and then head to the Downloads page by clicking the link on the left. For Windows you should choose one of the MSI installers depending on whether you're running on a 32- or 64-bit platform.

  2. Download and run the installer.

  3. In the installer, decide whether you only want to install Python for yourself, or for all users of your machine.

  4. Choose a location for the Python distribution. The default will be inC:\Python35 in the root of the C: drive. We don't recommended installing Python into Program Files because the virtualized file store used to isolate applications from each other in Windows Vista and later can interfere with easily installing third-party Python packages.

  5. On the Customize Python page of the wizard we recommend keeping the defaults, which use less than 40 MB of space.

  6. In addition to installing the Python runtime and standard library, the installer will register various file types, such as *.py files, with the Python interpreter.

  7. Once Python has been installed, you'll need to add Python to your system PATH environment variable. To do this, from the Control Panel choose System and Security, then System. Another way to get here easily is to hold down your Windows key and press the Break key on your keyboard. Using the task pane on the left choose Advanced System Settings to open the Advanced tab of the System Properties dialog. Click Environment variables to open the child dialog.

  8. If you have Administrator privileges you should be able to add the pathsC:\Python35 and C:\Python35\Scripts to the semicolon separated list of entries associated with the PATH system variable. If not, you should be able to create, or append to, a PATH variable specific to your user containing the same value.

  9. Now open a new console window — either Powershell or cmd will work fine — and verify that you can run python from the command line:

> python
Python 3.5.0 (v3.5.0:374f501f4567, Sep 13 2015, 02:27:37) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.

Welcome to Python!

The triple arrow prompt shows you that Python is waiting for your input.

At this point you might want to skip forward whilst we show how to install Python on Mac and Linux.


  1. For macOS you need to visit the official Python website at Head to the Download page by clicking the link on the left. On the Download page, find the macOS installer matching your version of macOS and click the link to download it.

  2. A DMG Disk Image file downloads, which you open from your Downloads stack or from the Finder.

  3. In the Finder window that opens you will see the file Python.mpkg multipackage installer file. Use the "secondary" click action to open the context menu for that file. From that menu, select Open.

  4. On some versions of macOS you will now be told that the file is from an unidentified developer. Press the Open button on this dialog to continue with the installation.

  5. You are now in the Python installer program. Follow the directions, clicking through the wizard.

  6. There is no need to customize the install, and you should keep the standard settings. When it's available, click the Install button to install Python. You may be asked for your password to authorize the installation. Once the installation completes click Close to close the installer.

  7. Now that Python 3 is installed, open a terminal window and verify that you can run Python 3 from the command line:

> python
Python 3.5.0 (default, Nov 3 2015, 13:17:02) 
[GCC 4.2.1 Compatible Apple LLVM 6.1.0 (clang-602.0.53)] on darwin
Type "help", "copyright", "credits" or "license" for more information.

Welcome to Python!

The triple arrow prompt shows that Python is waiting for your input.


  1. To install Python on Linux you will want to use your system's package manager. We'll show how to install Python on a recent version of Ubuntu, but the process is very similar on most other modern Linux distributions.

  2. On Ubuntu, first start the Ubuntu Software Center. This can usually be run by clicking on it's icon in the launcher. Alternatively, you can run it from the dashboard by searching on Ubuntu Software Center and clicking the selection.

  3. Once you're in the software center, enter the search term python 3.5 in the search bar in the upper right-hand corner and press return.

  4. One of the results you'll get will say Python (v3.5) with Python Interpreter (v3.5) in smaller type beneath it. Select this entry and click the Install button that appears.

  5. You may need to enter your password to install the software at this point.

  6. You should now see a progress indicator appear, which will disappear when installation is complete.

  7. Open a terminal (using Ctrl+Alt+T) and verify that you can run Python 3.5 from the command line:

$ python3.5
Python 3.5.0+ (default, Oct 11 2015, 09:05:38)
[GCC 5.2.1 20151010] on linux
Type "help", "copyright", "credits" or "license" for more information.

Welcome to Python!

The triple arrow prompt shows you that Python is waiting for your input.


Starting Python command line REPL

Now that Python is installed and running, you can immediately start using it. This is a good way to get to know the language, as well as a useful tool for experimentation and quick testing during normal development.

This Python command line environment is a Read-Eval-Print-Loop. Python will READ whatever input we type in, EVALuate it, PRINT the result and then LOOP back to the beginning. You'll often hear it referred to simply as the "REPL".

When started, the REPL will print some information about the version of Python you're running, and then it will give you a triple-arrow prompt. This prompt tells you that Python is waiting for you to type something.

Within an interactive Python session you can enter fragments of Python programs and see instant results. Let's start with some simple arithmetic:

>>> 2 + 2
>>> 6 * 7

As you can see, Python reads our input, evaluates it, prints the result, and loops around to do the same again.

We can assign to variables in the REPL:

>>> x = 5

Print their contents simply by typing their name:

>>> x

 Refer to them in expressions:

>>> 3 * x

Within the REPL you can use the special underscore variable to refer to the most recently printed value, this being one of very few obscure shortcuts in Python:

>>> _

Or you can use the special underscore variable in an expression:

>>> _ * 2


Remember that this useful trick only works at the REPL; the underscore doesn't have any special behavior in Python scripts or programs.

Notice that not all statements have a return value. When we assigned 5 to x there was no return value, only the side-effect of bringing the variable x into being. Other statements have more visible side-effects.

Try the following command:

>>> print('Hello, Python')
Hello, Python

You’ll see that Python immediately evaluates and executes this command, printing the string Hello, Python and returning you to another prompt. It's important to understand that the response here is not the result of the expression evaluated and displayed by the REPL, but is a side-effect of the print() function.

As an aside, print is one of the biggest differences between Python 2 and Python 3. In Python 3, the parentheses are required, whereas is Python 2 they were not. This is because in Python 3, print() is a function call. More on functions later.


Leaving the REPL

At this point, we should show you how to exit the REPL and get back to your system shell prompt. We do this by sending the end-of-file control character to Python, although unfortunately the means of sending this character varies across platforms.


If you're on Windows, press Ctrl+Z to exit.


If you're on Mac or Linux, press Ctrl+D to exit.

If you regularly switch between platforms and you accidentally press Ctrl+Z on a Unix-a-like system, you will inadvertently suspend the Python interpreter and return to your operating system shell. To reactivate Python by making it a foreground process again, simply run the fg command:

$ fg

Now press Enter and couple of times to get the triple arrow Python prompt back:


Code structure and significant indentation

Start your Python 3 interpreter:

> python

If on Windows or:

$ python3

On Mac or Linux.

The control flow structures of Python, such as for-loops, while-loops, and if-statements, are all introduced by statements which are terminated by a colon, indicating that the body of the construct is to follow. For example, for-loops require a body, so if you enter:

>>> for i in range(5):

Python will present you with a prompt of three dots to request that you provide the body. One distinctive (and sometimes controversial) aspect of Python is that leading whitespace is syntactically significant.

What this means is that Python uses indentation levels, rather the braces used by other languages, to demarcate code blocks.By convention, contemporary Python code is indented by four spaces for each level.

So when Python present us with the three dot prompt, we provide those four spaces and a statement to form the body of the loop:

...     x = i * 10

Our loop body will contain a second statement, so after pressing Return at the next three dot prompt we'll enter another four spaces followed by a call to the built-in print() function:

...     print(x)

To terminate our block, we must enter a blank line into the REPL:


With the block complete, Python executes the pending code, printing out the multiples of 10 less than 50:


Looking at at screenful of Python code, we can see how the indentation clearly matches — and in fact must match — the structure of the program which is as follows:

Figure 1.1: Whitespaces in the code

Even if we replace the code by gray lines, the structure of the program is clear as shown in the following image:

Figure 2.2 : Replaced code with grey lines

Each statement terminated by a colon starts a new line and introduces an additional level of indentation, which continues until a dedent restores the indentation to a previous level. Each level of indent is typically four spaces, although we'll cover the rules in more detail in a moment.

Python's approach to significant whitespace has three great advantages:

  1. It forces developers to use a single level of indentation in a code-block. This is generally considered good practice in any language because it makes code much more readable.
  2. Code with significant whitespace doesn't need to be cluttered with unnecessary braces, and you never need to have code-standard debates about where the braces should go. All code-blocks in Python code are easily identifiable and everyone writes them the same way.



  1. Significant whitespace requires that a consistent interpretation must be given to the structure of the code by the author, the Python runtime system and future maintainers who need to read the code. As a result you can never have code that contains a block from Python's point of view, but which doesn't look like it contains a block from a cursory human perspective.

The rules for Python indentation can seem complex, but they are quite straightforward in practice:

  • The whitespace you use can be either spaces or tabs. The general consensus is that spaces are preferable to tabs, and four spaces has become a standard in the Python community.

  • One essential rule is NEVER to mix spaces and tabs. The Python interpreter will complain, and your colleagues will hunt you down.

  • You are allowed to use different amounts of indentation at different times if you wish. The essential rule is that consecutive lines of code at the same indentation level are considered to be part of the same code block.

  • There are some exceptions to these rules, but they almost always have to do with improving code readability in other ways, for example by breaking up necessarily long statements over multiple lines.

This rigorous approach to code formatting is Programming as Guido intended it or, perhaps more appropriately, as Guido indented it! A philosophy of placing a high value on code qualities such as readability gets to the very heart of Python culture, something we'll take a short break to explore now.


Python culture

Many programming languages are at the center of a cultural movement. They have their own communities, values, practices, and philosophy, and Python is no exception. The development of the Python language itself is managed through a series of documents called Python Enhancement Proposals, or PEPs. One of the PEPs, called PEP 8, explains how you should format your code, and we follow its guidelines throughout this book. For example, it is PEP 8 which recommends that we use four spaces for indentation in new Python code.

Another of these PEPs, called PEP 20 is called “The Zen of Python”. It refers to 20 aphorisms describing the guiding principles of Python, only 19 of which have been written down. Conveniently, the Zen of Python is never further away than the nearest Python interpreter, as it can always be accessed from the REPL by typing:

>>> import this
The Zen of Python, by Tim Peters
Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!

Throughout this book we'll be highlighting particular nuggets of wisdom from the Zen of Python in moments of zen to understand how they apply to what we have learned. As we've just introduced Python significant indentation, this is a good time for our first moment of zen:

Figure 1.1: Moment of zen

In time, you'll come to appreciate Python's significant whitespace for the elegance it brings to your code, and the ease with which you can read other's.


Importing standard library modules

As mentioned earlier, Python comes with an extensive standard library, an aspect of Python that is often referred to as batteries included. The standard library is structured as modules, a topic we'll discuss in depth later. What's important at this stage is to know that you gain access to standard library modules by using the import keyword.

The basic form of importing a module is simply the import keyword followed by a space and the name of the module. For example, lets see how we can use the standard library's math module to compute square roots. At the triple-arrow prompt we type the following command:

>>> import math

Since import is a statement which doesn't return a value, Python doesn't print anything if the import succeeds, and we're immediately returned to the prompt. We can access the contents of the imported module by using the name of the module, followed by a dot, followed by the name of the attribute in the module that you need. Like many object oriented languages the dot operator is used to drill down into object structures. Being expert Pythonistas, we have inside knowledge that the math module contains a function called sqrt(). Let's try to use the following command:

>>> math.sqrt(81)

Getting help()

But how can we find out what other functions are available in the math module?

The REPL has a special function help() which can retrieve any embedded documentation from objects for which documentation has been provided, such as standard library modules.

To get help, simply type help at the prompt:

>>> help
Type help() for interactive help, or help(object) for help about object.

We'll leave you to explore the first form — for interactive help — in your own time. Here we'll go for the second option and pass the math module as the object for which we want help:

>>> help(math)
Help on module math:



   The following documentation is automatically generated from the    
   Python source files. It may be incomplete, incorrect or include 
   features that are considered implementation detail and may vary 
   between Python implementations. When in doubt, consult the module 
   reference at the location listed above.

 This module is always available. It provides access to the
 mathematical functions defined by the C standard.


 Return the arc cosine (measured in radians) of x.

You can use the space-bar to page through the help, and if you're on Mac or Linux use the arrow keys to scroll up and down.

Browsing through the functions, you'll can see that there's a math function, factorial, for computing factorials. Press Q to exit the help browser, and return us to the Python REPL.

Now practice using help() to request specific help on the factorial function:

>>> help(math.factorial)
Help on built-in function factorial in module math:

 factorial(x) -> Integral

 Find x!. Raise a ValueError if x is negative or non-integral.

Press Q to return to the REPL.

Let's use factorial() a bit. The function accepts an integer argument and return an integer value:

>>> math.factorial(5)
>>> math.factorial(6)

Notice how we need to qualify the function name with the module namespace. This is generally good practice, as it makes it abundantly clear where the function is coming from. That said, it can result in code that is excessively verbose.

Counting fruit with math.factorial()

Let's use factorials to compute how many ways there are to draw three fruit from a set of five fruit using some math we learned in school:

>>> n = 5
>>> k = 3
>>> math.factorial(n) / (math.factorial(k) * math.factorial(n - k))

This simple expression is quite verbose with all those references to the math module. The Python import statement has an alternative form that allows us to bring a specific function from a module into the current namespace by using the from keyword:

>>> from math import factorial
>>> factorial(n) / (factorial(k) * factorial(n - k))

This is a good improvement, but is still a little long-winded for such a simple expression.

A third form of the import statement allows us to rename the imported function. This can be useful for reasons of readability, or to avoid a namespace clash. Useful as it is, though, we recommend that this feature be used infrequently and judiciously:

>>> from math import factorial as fac
>>> fac(n) / (fac(k) * fac(n - k))


Different types of numbers

Remember that when we used factorial() alone it returned an integer. But our more complex expression above for calculating combinations is producing a floating point number. This is because we've used /, Python's floating-point division operator. Since we know our operation will only ever return integral results, we can improve our expression by using //, Python’s integer division operator:

>>> from math import factorial as fac
>>> fac(n) // (fac(k) * fac(n - k))

What's notable is that many other programming languages would fail on the above expression for even moderate values of n. In most programming languages, regular garden variety signed integers can only store values less than {ParseError: KaTeX parse error: Expected 'EOF', got '}' at position 1: }̲2\times10^{31}}:

>>> 2**31 - 1

However, factorials grow so fast that the largest factorial you can fit into a 32-bit signed integer is 12! since 13! is too large:

>>> fac(13)

In most widely used programming languages you would need either more complex code or more sophisticated mathematics merely to compute how many ways there are to draw 3 fruits from a set of 13!. Python encounters no such problems and can compute with arbitrarily large integers, limited only by the memory in your computer. To demonstrate this further, let's try the larger problem of computing how many different pairs of fruit we can pick from 100 different fruits (assuming we can lay our hands on so many fruit!):

>>> n = 100
>>> k = 2
>>> fac(n) // (fac(k) * fac(n - k))

Just to emphasize how large the size of the first term of that expression is, calculate 100! on it's own:

>>> fac(n)

This number is vastly larger even than the number of atoms in the known universe, with an awful lot of digits. If, like us, you're curious to know exactly how many digits, we can convert our integer to a text string and count the number of characters in it like this:

>>> len(str(fac(n)))

That's definitely a lot of digits. And a lot of fruit. It also starts to show how Python's different data types — in this case, integers, floating point numbers, and text strings — work together in natural ways. In the next section we'll build on this experience and look at integers, strings, and other built-in types in more detail.


Scalar data types: integers, floats, None and bool

Python comes with a number of built-in datatypes. These include primitive scalar types like integers as well as collection types like dictionaries. These built-in types are powerful enough to be used alone for many programming needs, and they can be used as building blocks for creating more complex data types.

The basic built-in scalar types we'll look at are:

  • int — signed, unlimited precision integers
  • float — IEEE 754 floating-point numbers
  • None — a special, singular null value
  • booltrue/false boolean values

For now we'll just be looking at their basic details, showing their literal forms and how to create them.


We've already seen Python integers in action quite a lot. Python integers are signed and have, for all practical purposes, unlimited precision. This means that there is no pre-defined limit to the magnitude of the values they can hold.

Integer literals in Python are typically specified in decimal:

>>> 10

They may also be specified in binary with a 0b prefix:

>>> 0b10

There may also be a octal, with a 0o prefix:

>>> 0o10

If its a hexadecimal we use the 0x prefix:

>>> 0x10

We can also construct integers by a call to the int constructor which can convert from other numeric types, such as floats, to integers:

>>> int(3.5)

Note that, when using the int constructor, the rounding is always towards zero:

>>> int(-3.5)
>>> int(3.5)

We can also convert strings to integers as follows:

>>> int("496")

Be aware, though, that Python will throw an exception (much more on those later!) if the string doesn't represent an integer.

You can even supply an optional number base when converting from a string. For example, to convert from base 3 simply pass 3 as the second argument to the constructor:

>>> int("10000", 3)



Floating point numbers are supported in Python by the float type. Python floats are implemented as IEEE-754 double-precision floating point numbers with 53 bits of binary precision. This is equivalent to between 15 and 16 significant digits in decimal.

Any literal number containing a decimal point is interpreted by Python as a float:


Scientific notation can be used, so for large numbers — such as {ParseError: KaTeX\ parse error: Expected 'EOF', got '}' at position 1: }̲3\times10^8{/}, the approximate speed of light in metres per second — we can write:

>>> 3e8

and for small numbers like Planck's constant {ParseError: KaTeX parse error:\ Expected 'EOF', got '}' at position 1: }̲1.616\times10^} we can enter:

>>> 1.616e-35

Notice how Python automatically switches the display representation to the most readable form.

As for integers, we can convert to floats from other numeric or string types using the float constructor. For example, the constructor can accept an int:

>>> float(7)

The float constructor can also accept a string as follows:

>>> float("1.618")


Special floating point values

By passing certain strings to the float constructor, we can create the special floating point value NaN (short for Not aNumber) and also positive and negative infinity:

>>> float("nan")
>>> float("inf")
>>> float("-inf")

Promotion to float

The result of any calculation involving int and float is promoted to a float:

>>> 3.0 + 1

You can read more about Python's number types in the Python documentation.


Python has a special null value called None, spelled with a capital N. None is frequently used to represent the absence of a value. The Python REPL never prints None results, so typing None into the REPL has no effect:

>>> None

The null value None can be bound to variable names just like any other object:

>>> a = None

and we can test whether an object is None by using Python's is operator:

>>> a is None

We can see here that the response is True, which brings us conveniently on to the bool type.


The bool type represents logical states and plays an important role in several of Python's control flow structures, as we'll see shortly. As you would expect there are two bool values, True and False, both spelled with initial capitals:

>>> True
>>> False

There is also a bool constructor which can be used to convert from other types to bool. Let's look at how it works. For ints, zero is considered falsey and all other values truthy:

>>> bool(0)
>>> bool(42)
>>> bool(-1)

We see the same behavior with floats where only zero is considered falsey:

>>> bool(0.0)
>>> bool(0.207)
>>> bool(-1.117)
>>> bool(float("NaN"))

When converting from collections, such as strings or lists, only empty collections are treated as falsey. When converting from lists — which we'll look at shortly — we see that only the empty list (shown here in it's literal form of []) evaluates to False:

>>> bool([])
>>> bool([1, 5, 9])

Similarly, with strings only the empty string, "", evaluates to False when passed to bool:

>>> bool("")
>>> bool("Spam")

In particular, you cannot use the bool constructor to convert from string representations of True and False:

>>> bool("False")

Since the string False is not empty, it will evaluate to True. These conversions to bool are important because they are widely used in Pythonif-statements and while-loops which accept bool values in their condition.


Relational operators

Boolean values are commonly produced by Python’s relational operators which can be used for comparing objects. Two of the most widely used relational operators are Python's equality and inequality tests, which actually test for equivalence or inequivalence of values. That is, two objects are equivalent if one could use used in place of the other. We'll learn more about the notion of object equivalence later in the book. For now, we'll compare simple integers.

Let's start by assigning — or binding — a value to a variable g:

>>> g = 20

We test for equality with == as shown in the following command:

>>> g == 20
>>> g == 13

For inequality we use !=:

>>> g != 20
>>> g != 13


Rich comparison operators

We can also compare the order of quantities using the rich comparison operators. Use < to determine if the first argument is less than the second:

>>> g < 30

Likewise, use > to determine if the first is greater than the second:

>>> g > 30

You can test less-than or equal-to with <=:

>>> g <= 20

We can use the greater-than or equal-to with >= ,shown as follows:

>>> g >= 20

If you have experience with relational operators from other languages, then Python's operators are probably not surprising at all. Just remember that these operators are comparing equivalence, not identity, a distinction we'll cover in detail in coming chapters.


Control flow: if-statements and while-loops

Now that we've examined some basic built-in types, let's look at two important control flow structures which depend on conversions to the bool type: if-statements and while-loops.

Conditional control flow: The if-statement

Conditional statements allow us to branch execution based on the value of an expression. The form of the statement is the if keyword, followed by an expression, terminated by a colon to introduce a new block. Let's try this at the REPL:

>>> if True:

Remembering to indent four spaces within the block, we add some code to be executed if the condition is True, followed by a blank line to terminate the block:

...     print("It's true!")
It's true!

At this point the block will execute, because self-evidently the condition is True. Conversely, if the condition is False, the code in the block does not execute:

>>> if False:
...     print("It's true!")

The expression used with the if-statement will be converted to a bool just as if the bool() constructor had been used, so:

>>> if bool("eggs"):
...     print("Yes please!")
Yes please!

If the value is exactly equivalent to something, we then use the if command as follows:

>>> if "eggs":
...     print("Yes please!")
Yes please!

Thanks to this useful shorthand, explicit conversion to bool using the bool constructor is rarely used in Python.


The if-statement supports an optional else clause which goes in a block introduced by the else keyword (followed by a colon) which is indented to the same level as the if keyword. Let's start by creating (but not finishing) an if-block:

>>> h = 42
>>> if h > 50:
...     print("Greater than 50")


To start the else block in this case, we just omit the indentation after the three dots:

... else:
...     print("50 or smaller")
50 or smaller


For multiple conditions you might be tempted to do something like this:

>>> if h > 50:
...     print("Greater than 50")
... else:
...     if h < 20:
...         print("Less than 20")
...     else:
...         print("Between 20 and 50")
Between 20 and 50

Whenever you find yourself with an else-block containing a nested if  statement, like this, you should consider using Python's elif keyword which is a combined else-if.

As the Zen of Python reminds us, Flat is better than nested:

>>> if h > 50:
...     print("Greater than 50")
... elif h < 20:
...     print("Less than 20")
... else:
...      print("Between 20 and 50")
Between 20 and 50

This version is altogether easier to read.

Conditional repetition: the while-loop

Python has two types of loop: for-loops and while-loops. We've already briefly encountered for-loops back when we introduced significant whitespace, and we'll return to them soon, but right now we'll cover while-loops.

The While-loops in Python are introduced by the while keyword, which is followed by a boolean expression. As with the condition for if-statements, the expression is implicitly converted to a boolean value as if it has been passed to the bool() constructor. The while statement is terminated by a colon because it introduces a new block.

Let's write a loop at the REPL which counts down from five to one. We'll initialize a counter variable called c to five, and keep looping until we reach zero. Another new language feature here is the use of an augmented-assignment operator, -=, to subtract one from the value of the counter on each iteration. Similar augmented assignment operators exist for the other basic math operations such as addition and multiplication:

>>> c = 5
>>> while c != 0:
...     print(c)
...     c -= 1

Because the condition — or predicate — will be implicitly converted to bool, just as if a call to the bool() constructor were present, we could replace the above code with the following version:

>>> c = 5
>>> while c:
...     print(c)
...     c -= 1

This works because the conversion of the integer value of c to bool results in True until we get to zero which converts to False. That said, to use this short form in this case might be described as un-Pythonic, because, referring back to the Zen of Python, explicit is better than implicit. We place higher value of the readability of the first form over the concision of the second form.

The While-loops are often used in Python where an infinite loop is required. We achieve this simply by passing True as the predicate expression to the while construct:

>>> while True:
...     print("Looping!")

Now you're probably wondering how we get out of this loop and regain control of our REPL! Simply press Ctrl+C:

Traceback (most recent call last):
File "<stdin>", line 2, in <module>

Python intercepts the key stroke and raises a special exception which terminates the loop. We'll be talking much more about what exceptions are, and how to use them, later in Chapter 6Exceptions.

Exiting loops with break

Many programming languages support a loop construct which places the predicate test at the end of the loop rather than at the beginning. For example, C, C++, C# and Java support the do-while construct. Other languages have repeat-until loops instead or as well. This is not the case in Python, where the idiom is to use while True together with an early exit, facilitated by the break statement.

The break statement jumps out of the loop — and only the innermost loop if severals loops have been nested — continuing execution immediately after the loop body.

Let's look at an example of break, introducing a few other Python features along the way, and examine it line-by-line:

>>> while True:
...     response = input()
...     if int(response) % 7 == 0:
...         break

We start with a while True: for an infinite loop. On the first statement of the while block we use the built-in input() function to request a string from the user. We assign that string to a variable called response.

We now use an if-statement to test whether the value provided is divisible by seven. We convert the response string to an integer using the int() constructor and then use the modulus operator, %, to divide by seven and give the remainder. If the remainder is equal to zero, the response was divisible by seven, and we enter the body of the if-block.

Within the if-block, now two levels of indentation deep, we start with eight spaces and use the break keyword. break terminates the inner-most loop — in this case the while-loop — and causes execution to jump to the first statement after the loop.

Here, that statement is the end of the program. We enter a blank line at the three dots prompt to close both the if-block and the while-block. Our loop will start executing, and will pause at the call to input() waiting for us to enter a number. Let's try a few:


As soon as we enter a number divisible by seven the predicate becomes True, we enter the if-block, and then we literally break out of the loop to the end of program, returning us to the REPL prompt.



  • Starting out with Python
    • Obtaining and installing Python 3

    • Starting the Read-Eval-Print-Loop or REPL

    • Simple arithmetic

    • Creating variables by binding objects to names

    • Printing with the built-in print() function

    • Exiting the REPL with Ctrl+Z (Windows) or Ctrl+D (Unix)

  • Being Pythonic

    • Significant indentation

    • PEP 8 - The Style Guide for Python Code

    • PEP 20 - The Zen of Python

  • Importing modules with the import statement in various forms

  • Finding and browsing help()

  • Basic types and control flow

    • ints, floats, None, and bool, plus conversions between them

    • Relational operators for equality and ordering tests

    • The if-statements with else and elif blocks

    • The while-loops with implicit conversion to bool

    • Interrupting infinite loops with Ctrl+C

    • Breaking out of loops with break

  • Requesting text from the user with input()

  • Augmented assignment operators


About the Authors

  • Robert Smallshire

    Robert Smallshire is a founding director of Sixty North, a software consulting and training business in Norway providing services throughout Europe, and which uses Python extensively. Robert has worked in senior architecture and technical management roles for several software companies providing tools in the energy sector. He has dealt with understanding, designing, advocating and implementing effective architectures for sophisticated scientific and enterprise software in Python, C++, C# and F# and Javascript. Robert is a regular speaker at conferences, meetups and corporate software events and can be found speaking about topics as diverse as behavioural microeconomics in software development to implementing web services on 8-bit microcontrollers. He is organiser of the Oslo Python group and holds a Ph.D. in a natural science.

    Browse publications by this author
  • Austin Bingham

    Austin Bingham is a founding director of Sixty North, a software consulting, training, and application development company. A native of Texas, in 2008 Austin moved to Stavanger, Norway where he helped develop industry-leading oil reservoir modeling software in C++ and Python. Prior to that he worked at National Instruments developing LabVIEW, at Applied Research Labs (Univ. of Texas at Austin) developing sonar systems for the U.S. Navy, and at a number of telecommunications companies. He is an experienced presenter and teacher, having spoken at numerous conferences, software groups, and internal corporate venues. Austin is also an active member of the open source community, contributing regularly to various Python and Emacs projects, and he's the founder of Stavanger Software Developers, one of the largest and most active social software groups in Stavanger. Austin holds a Master of Science in Computer Engineering from the University of Texas at Austin.

    Browse publications by this author

Latest Reviews

(6 reviews total)
The book arrived in good conditions.
I have finished more than half the book and the topics covered are just right for a Python beginner.
Book appears well-written and well-proofread (haven't tried all the sample programs yet, so I can't state for certain). The only negative is that, like all Packt books, the first 50 or so pages is a re-hash of introduction to Python, book format and conventions, notes on authors, how to install Python, etc. This is all the same in every Packt Python book, and could be condensed to half as many pages or less without losing anything. It appears to be spread out just to take up more room, to fill out the book to a higher page count. Many of these pages have only a few sentences per page. Fortunately the book was discounted heavily, so I don't feel cheated. If I had paid full retail price I would be annoyed by this.
The Python Apprentice
Unlock this book and the full library FREE for 7 days
Start now