I don’t know about you—for me, the boring part of learning a new language is the mandatory listing of basic types, operators, and control structures. Whenever I try to memorize the finer points of loop syntax and operator precedence, that information slips right off my brain. It only sticks once I start writing code.
For that reason, I won’t bog you down in details that you can look up yourself later, when you’re confronted with real code. I’ll keep this section on types, operators, and control structures as brief as possible, providing a broad overview and only zooming in on those few details that are important for this book.
Python comes with the data types you expect: integers, floating-point numbers, booleans, strings—the works:
| an_integer = 42 |
| a_float = 0.5 |
| a_boolean = True |
| a_string = "abc" |
As for Python’s operators, you’ll probably find them familiar across the board:
| an_integer + a_float # => 42.5 |
| an_integer >= a_float # => True |
| a_float * 2 # => 1.0 |
| an_integer / 10 # => 4.2 |
| an_integer % 10 # => 2 |
| not a_boolean # => False |
| a_boolean or False # => True |
| a_string + 'def' # => 'abcdef' |
Compared to some other dynamic languages like JavaScript or Perl, Python is strict about mixing types. While the language does cast types automatically in some cases, potentially ambigous operations usually result in an error:
| # Implicit cast from an integer to a boolean: |
| not 10 # => False |
| |
| # Failing implicit cast from an integer to a string: |
| "20" + 20 # => TypeError: must be str, not int |
If you need to convert Python values from one type to the other, you generally do so explicitly, with functions such as str, int, and bool:
| "20" + str(20) # => '2020' |
We’ll get a closer look at Python’s strings in a minute—but first, let’s look at variables that contain multiple values.
Every modern language supports variables with multiple ordered values, usually called “arrays,” “lists,” or “vectors.” Python has two such multi-valued collection types: lists and tuples.
Here is what tuples look like:
| a_tuple = (3, 9, 12, 7, 1, -4) |
| len(a_tuple) # => 6 |
| a_tuple[2] # => 12 |
| a_tuple[2:5] # => (12, 7, 1) |
You create a tuple by wrapping a sequence of comma-separated values in round brackets. The preceding code demonstrates a couple of things you can do with tuples: getting their length, and getting one or more of their elements (using zero-based indexes).
Tuples are immutable: once you create one, it cannot change. If you want a mutable collection of values… that’s what lists are for. They look similar to tuples—only they use square brackets, and they are mutable:
| a_list = [10, 20, 30] |
| a_list[1] = a_list[1] + 2 |
| a_list.append(100) |
| a_list # => [10, 22, 30, 100] |
Python being dynamic, tuples and lists can contain values of any type, or even a mix of types. As an example, each element in the following list has a different type, including a tuple and another list:
| a_mixed_list = ['a', 42, False, (10, 20), 99.9, a_list] |
Lists and tuples will both appear in this book’s source code—but they won’t get the spotlight. The most common collection we’ll use, by far, is the powerful array type from the NumPy library. There’s no need to linger on arrays here, because you’re going to get familiar with them as you read the book. Just know that they look a bit like Python’s lists, but they have multiple dimensions—so they’re perfect to represent matrices, which are a common data structure in ML.
In this appendix, we’re going to skip over the dictionary—Python’s take on key–value collections. The reason we’re passing over dictionaries is that we don’t happen to use them in the book. However, if you want to do some Python coding of your own, then dictionaries are one of the first features you should look up.
We’re almost done with Python’s basic types. We only need to give a closer look at strings.
You can define a string with either double or single quotes:
| s1 = "This is a string" |
| s2 = 'this is also a string' |
| s1 + " and " + s2 # => 'This is a string and this is also a string' |
Python programmers tend to use double quotes, and switch to single quotes when the string itself contains double quotes:
| print('Yup, this is yet another "Hello, World!" example') |
A string behaves pretty much like a tuple of characters, which is why we looked at collections first. In particular, you can index a string’s individual characters:
| s3 = s2[8:12] |
| s3 # => 'also' |
There is another way in which Python’s strings look like tuples, and it will please the functional programmers among you (you know who you are): strings are immutable. You cannot modify a string in place—you have to create a new string, as I did in the preceding code.
One feature that we use a lot in this book is string interpolation—a way to embed variables in a string. Python offers a few ways to do string interpolation, but we’re going to stick with the “classic” style, because it’s compatible with all modern versions of Python. It looks like this:
| a = 1 |
| b = 99.12345 |
| c = 'X' |
| "The values of these variables are %d, %.2f, and %s" % (a, b, c) |
| # => The values of these variables are 1, 99.12, and X |
The % sign separates the string from a tuple of values that must be embedded in it. The embedding positions are marked by special codes, that are also prefixed by a %. In particular, %d means “embed as a decimal number,” %s means “embed as a string,” and %.2f means “embed as a floating-point number rounded to two decimal places.”
Finally, if you want to print a percent sign inside an interpolated string, you need to escape it by typing double percent signs:
| "Less than %.d%% of ML books have a hammer on the cover" % a |
| # => Less than 1% of ML books have a hammer on the cover |
Python comes with the usual C-style control structures: if, while, for, and their ilk. We already saw how to use if in our first Python example, in What Python Looks Like. As for while, we won’t use it in this book.
On the other hand, we’ll use for loops all the time. Here is what they look like:
| for i in range(4): |
| if i % 2 == 0: |
| print("%d is an even number" % i) |
| else: |
| print("%d is an odd number" % i) |
The for loop iterates over the values in the range:
| 0 is an even number |
| 1 is an odd number |
| 2 is an even number |
| 3 is an odd number |
Note that the range includes 0, but excludes 4.
Experienced Python coders tend to shun for loops, in favor of more elegant constructs inspired by functional programming. We won’t use those constructs in this book. If you’re curious, check out Python’s list comprehension.[44]
With that, we’ve completed our tour of Python’s basic types, operators, and control structures. Let’s move on to another fundamental feature of the language: functions.