Title
Part I Introduction to Programming
Chapter 1. Introduction
Chapter 2. Getting Started
Chapter 3. Introduction to Programming
Chapter 4. Functions
Chapter 5. Containers
Chapter 6. String Manipulation
Chapter 7. Loops
Chapter 8. Modules
Chapter 9. Files
Chapter 10. Bringing It All Together
Chapter 11. Practice
Part II Introduction to Object-Oriented Programming
Chapter 12. Programming Paradigms
Chapter 13. The Four Pillars of Object-Oriented
Programming
Chapter 14. More Object-Oriented Programming
Chapter 15. Bringing It All Together
Part III Introduction to Programming Tools
Chapter 16. Bash
Chapter 17. Regular Expressions
Chapter 18. Package Managers
Chapter 19. Version Control
Chapter 20. Bringing It All Together
Part IV Introduction to Computer Science
Chapter 21. Data Structures
Chapter 22. Algorithms
Part V Landing a Job
Chapter 23. Best Programming Practices
Chapter 24. Your First Programming Job
Chapter 25. Working on a Team
Chapter 26. Further Learning
Chapter 27. Next Steps
Acknowledgements
Citations
Copyright © 2016 by Cory Althoff.
All rights reserved. This book or any portion thereof may not
be reproduced or used in any manner whatsoever without the
express written permission of the publisher except for the use
of brief quotations in a book review.
Version 3
Endgame First
The way I learned to program is the opposite of how computer
science is usually taught, and I structured the book to follow
my approach. Traditionally, you spend a lot of time learning
theory—so much so, that many computer science graduates
come out of school not knowing how to program. In his blog
“Why Can’t Programmers.. Program?,” Jeff Atwood writes,
“Like me, the author is having trouble with the fact that 199
out of 200 applicants for every programming job can’t write
code at all. I repeat: they can’t write any code whatsoever.”
This revelation led Atwood to create the FizzBuzz coding
challenge, a programming test used in interviews to weed out
candidates. Most people fail the challenge, and that’s why you
spend so much of this book learning the skills you will use in
practice. Don’t worry, you also learn how to pass the FizzBuzz
test.
In The Art of Learning , Josh Waitzkin of Searching for Bobby
Fischer fame describes how he learned how to play chess in
reverse. Instead of studying opening moves, he started
learning the endgame (when there are only a few pieces left on
the board) first. This strategy gave him a better understanding
of the game, and he went on to win many championships.
Similarly, I think it is more efficient to learn to program first,
then learn theory later, once you are dying to know how
everything works. That is why I wait until Part IV of the book
to introduce computer science theory, and I keep it to a
minimum. While theory is important, it will be even more
valuable once you already have programming experience.
Sticking with It
If you don’t have any programming experience and are
nervous about making this journey, I want you to know you
are capable of it. There are some common misconceptions
about programmers like they all are great at math. They aren’t.
You don’t need to be great at math to learn to program, but it
does take hard work. With that said, a lot of the material
covered in this book is easier to learn than you think.
To improve your programming skills, you should practice
programming every day. The only thing that will hold you
back is not sticking with it, so let’s go over two ways to make
sure you do.
When I was getting started, I used a checklist to ensure I
practiced every day, and it helped me stay focused.
If you need extra help, Tim Ferriss, a productivity expert,
recommends the following technique to stay motivated: give
money to a friend or family member with instructions to return
it to you upon completion of your goal within a given time
frame, or donate it to an organization you dislike if you fail.
Vocabulary
FizzBuzz : A programming test used in interviews to weed out
candidates.
Operating system : A program that is the middleman between
the physical components of the computer and you.
Graphical user interface (GUI) : The part of your operating
system you see when you look at your computer screen.
Windows : Microsoft’s operating system.
Unix : An operating system created in the 1970s. Apple’s
operating system is based on Unix.
Linux : An open-source operating system used by the majority
of the world’s servers.
Open-source : Software that is not owned by a company or
individual, but is instead maintained by a group of volunteers.
Server : A computer or computer program that performs tasks,
like hosting a website.
Unix-like operating systems : Unix and Linux.
Challenge
1. Create a daily checklist that includes practicing
programming.
Chapter 2.
Getting Started
“A good programmer is someone who always looks both ways
before crossing a one-way street.”
~Doug Linder
What Is Programming
Programming is writing instructions for a computer to
execute. The instructions might tell the computer to print
Hello, World! , scrape data from the Internet, or read the
contents of a file and save them to a database. These
instructions are called code . Programmers write code in many
different programming languages. In the past, programming
was much harder, as programmers were forced to use cryptic,
low-level programming languages like assembly language .
When a programming language is low-level, it is closer to
being written in binary (0s and 1s) than a high-level
programming language (a programming language that reads
more like English), and thus is harder to understand. Here is a
simple program written in an assembly language:
# http://tinyurl.com/z6facmk
global _start
section .text
_start:
mov rax, 1
mov rdi, 1
mov rsi, message
mov rdx, 13
syscall
; exit(0)
mov eax, 60
xor rdi, rdi
syscall
message:
db "Hello, World!", 10
print
(
"Hello, World!"
)
What Is Python
Python is an open-source programming language created by
Dutch programmer Guido van Rossum, named after the British
sketch comedy group Monty Python. One of van Rossum’s
key insights was that programmers spend more time reading
code than writing it, so he created an easy-to-read language.
Python is one of the most popular and easiest to learn
programming languages in the world. It runs on all the major
operating systems and computers and is used to build web
servers, create desktop applications, and everything in
between. Because of its popularity, there is a significant
demand for Python programmers.
Installing Python
To follow the examples in this book, you need to have Python
Version 3 installed. You can download Python for Windows
and Unix at http://python.org/downloads . If you are on
Ubuntu, Python 3 comes installed by default. Make sure you
download Python 3, not Python 2. Some of the examples in
this book will not work if you are using Python 2.
Python is available for 32-bit and 64-bit computers. If you
purchased your computer after 2007, it is most likely a 64-bit
computer. If you aren’t sure, an Internet search should help
you figure it out.
If you are on Windows or a Mac, download the 32- or 64-bit
version of Python, open the file, and follow the instructions.
You can also visit
http://theselftaughtprogrammer.io/installpython for videos
explaining how to install Python on each operating system.
Troubleshooting
From this point forward, you need to have Python installed. If
you are having problems installing Python, please skip ahead
to Chapter 11 to the section titled “Getting Help.”
1
print
(
"Hello, World!"
)
Vocabulary
Programming : Writing instructions for a computer to
execute.
Code : The instructions programmers write for a computer to
execute.
Low-level programming language : A programming
language closer to being written in binary (0s and 1s) than a
high-level programming language.
Assembly language : A type of difficult-to-read programming
language.
High-level programming language : A programming
language that reads more like English than a low-level
programming language.
Python : The easy-to-read, open-source programming
language you will learn to use in this book. Created by Guido
van Rossum and named after the British sketch comedy group
Monty Python.
Challenge
1. Try to print something other than Hello, World! .
Solution: http://tinyurl.com/noeujfu .
Chapter 3.
Introduction to Programming
“It’s the only job I can think of where I get to be both an engineer and an artist. There’s an
incredible, rigorous, technical element to it, which I like because you have to do very precise
thinking. On the other hand, it has a wildly creative side where the boundaries of imagination are
the only real limitation.”
~Andy Hertzfeld
Our first program printed Hello, World! Let’s print it a hundred times. Type the following
code into the interactive shell (print needs to be indented exactly four spaces):
1
# http://tinyurl.com/h79ob7s
2
3
4
5
for
i
in
range
(
100
):
print
(
"Hello, World!"
)
Your shell should print Hello, World! a hundred times. Even though you will probably never
need to print Hello, World! a hundred times, this example shows you how powerful
programming is. Can you think of anything else you can do a hundred times so easily? I can’t. That
is the power of programming.
Examples
From now on, code examples will look like this:
1
# http://tinyurl.com/h4qntgk
2
3
4
5
for
i
in
range
(
100
):
print
(
"Hello, World!"
)
Comments
A comment is a line (or part of a line) of code written in English (or another language), preceded by
a symbol telling the programming language you are using to ignore that line (or part of a line) of
code. In Python, the pound symbol is used to create comments.
A comment explains what a line of code does. Programmers use comments to make the line of code
easier to understand for whoever reads it. You can write whatever you want in a comment, as long
as it is only one line long:
1
# http://tinyurl.com/hut6nwu
2
3
4
# This is a comment
print
(
"Hello, World!"
)
1
# http://tinyurl.com/jpzlwqq
2
3
4
5
# print Hello, World!
print
(
"Hello, World!"
)
It is unnecessary because it is already very clear what the line of code does. Here is an example of a
good comment:
1
# http://tinyurl.com/z52c8z8
2
3
4
5
6 import
7 math
8
9
10
# length of a diagonal
l
=
4
w
=
10
d
=
math.sqrt(l
*
*
2
+
w
*
*
2
)
Even if you understood exactly how this code works, you still might not know how to calculate the
length of a diagonal of a rectangle, so the comment is useful.
Printing
You are not limited to printing Hello, World! in your programs. You can print whatever you’d
like, as long as you surround it with quotes:
1
# http://tinyurl.com/zh5g2a3
2
3
4
print
(
"Python"
)
>> Python
1
# http://tinyurl.com/hhwqva2
2
3
4
print
(
"Hola!"
)
>> Hola!
Lines
Python programs are made up of lines of code. Take a look at this program:
1
# http://tinyurl.com/jq2w5ro
2
3
4
5
6 # line1
# line2
# line3
There are three lines of code. It is useful to refer to each piece of code by the line it is on. In IDLE,
you can go to “Edit” and select “Go to Line” to jump to a particular line in your program. You can
only enter one line of code into the shell at once. You cannot copy and paste multiple lines.
Sometimes a piece of code is long and takes up more than one line. Code surrounded by three
quotes, parentheses, brackets and braces can extend to a new line:
1
# http://tinyurl.com/zcdx3yo
2
3
4
5
6 print
(
"""This is a really really
code."""
)
You can use a backward slash \ to extend code to the next line when you wouldn’t normally be able
to:
1
# http://tinyurl.com/hjcf2sa
2
3
4
5
6 print
\
(
"""This is a really really
This example and the previous example have the same output. The slash allowed me to put
(“““This is a really really really long line of code.”””) and print
on separate lines, which otherwise is not allowed. This practice is not very common in, but I do it
throughout the book to make examples narrow so that they will fit on eBook readers with small
screens.
Keywords
Programming languages like Python have words with special meanings, called keywords . for , a
keyword you’ve already seen, is used to execute code multiple times. You will learn more keywords
throughout this chapter.
Spacing
Let’s take another look at your program that prints Hello, World! a hundred times:
1
# http://tinyurl.com/glp9xq6
2
3
4
5
for
i
in
range
(
100
):
print
(
"Hello, World!"
)
As I noted earlier, print is indented four spaces. I will cover why shortly, but it lets Python know
when blocks of code begin and end. In the meantime, please be aware that whenever you see an
indent in an example, it is an indent of four spaces. Without proper spacing, your program will not
work.
Other programming languages do not use spacing like this; they use keywords or brackets instead.
Here is the same program written in another programming language called JavaScript:
1
# http://tinyurl.com/hwa2zae
2
3
4
5
6 # This is a JavaScript program.
7
8 # It will not work.
9
10
for
(i
=
0
; i <
100
; i
+
+
) {
console.log(
"Hello, World!"
);
Python proponents believe the required use of proper spacing makes Python less tedious to read and
write than other languages. Like in the example above, even when space is not part of the
programming language, programmers include it to make their code easier to read.
Data Types
Python groups data into different categories called data types . In Python, each data value, like 2 or
“Hello, World!” , is called an object . You will learn more about objects in Part II, but for
now think of an object as a data value in Python with three properties: identity, data type, and value.
An object’s identity is its location in your computer’s memory, which never changes. The data type
of an object is the category of data the object belongs to, which determines the properties the object
has and never changes. The value of an object is the data it represents—the number 2 , for example,
has a value of 2 .
“Hello, World!” is an object with the data type str , short for string , and the value “Hello,
World!” . When you refer to an object with the data type str , you call it a string. A string is a
sequence of one or more characters surrounded by quotes. A character is a single symbol like a or
1 . You can use single quotes or double quotes, but the quotes at the beginning and end of a string
must match:
1
# http://tinyurl.com/hh5kjwp
2
3
4
"Hello, World!"
1
# http://tinyurl.com/heaxhsh
2
3
4
'Hello, World!'
1
# http://tinyurl.com/guoc4gy
2
3
4
2.2
+
2.2
>> 4.4
Objects with a bool data type are called booleans , and have a value of True or False :
1
# http://tinyurl.com/jyllj2k
2
3
4
True
>> True
1
# http://tinyurl.com/jzgsxz4
2
3
4
False
>> False
Objects with a data type NoneType always have the value None . They are used to represent the
absence of value:
1
# http://tinyurl.com/h8oqo5v
2
3
4
None
I explain how to use the different data types throughout this chapter.
1
# http://tinyurl.com/zs65dp8
2
3
4
2
+
2
>> 4
1
# http://tinyurl.com/gs9nwrw
2
3
4
2
-
2
>> 0
1
# http://tinyurl.com/hasegvj
2
3
4
4
/
2
>> 2.0
1
# http://tinyurl.com/z8ok4q3
2
3
4
2
*
2
>> 4
A constant is a value that never changes. Each of the numbers in the previous example is a
constant; the number two will always represent the value 2. A variable , on the other hand, refers to
a value that can change. A variable consists of a name made up of one or more characters. That
name is assigned a value using the assignment operator (the = sign).
Some programming languages require the programmer to include variable “declarations” that tell
the programming language what data type the variable will be. For example, in the C programming
language, you create a variable like this:
1
# Do not run.
2
3
4
5
6
7
8
int
a;
a
=
144
;
Python makes it simpler; you create a variable simply by assigning a value to it with the assignment
operator:
1
# http://tinyurl.com/hw64mrr
2
3
4
5
b
=
100
>> 100
Here is how to change the value of a variable:
1
# http://tinyurl.com/hw97que
2
3
4
5
6 x
7 =
100
8
9 x
x
=
200
>> 100
>> 200
You can also use two variables to perform arithmetic operations:
1
# http://tinyurl.com/z8hv5j5
2
3
4
5
6 x
7 =
10
8
9 y
=
10
z
=
x
+
y
a
=
x
-
y
>> 20
>> 0
Often when programming, you want to increment (increase) or decrement (decrease) the value of a
variable. Because this is such a standard operation, Python has a special syntax—a shortcut—for
incrementing and decrementing variables. To increment a variable, you assign the variable to itself,
and on the other side of the equals sign you add the variable to the number you want to increment
by:
1
2 # http://tinyurl.com/zvzf786
3
4
5
6 x
=
10
x
=
x
+
1
>> 11
To decrement a variable, you do the same thing, but instead subtract the number you want to
decrement by:
1
2 # http://tinyurl.com/gmuzdr9
3
4
5
6 x
=
10
x
=
x
-
1
>> 9
These examples are perfectly valid, but there is a shorter method you should use instead:
1
2 # http://tinyurl.com/zdva5wq
3
4
5
6 x
=
10
x
+
=
1
>> 11
1
# http://tinyurl.com/jqw4m5r
2
3
4
5
6 x
=
10
x
-
=
1
>> 9
Variables are not limited to storing integer values. They can refer to any data type:
1
# http://tinyurl.com/jsygqcy
2
3
4
hi
=
"Hello, World!"
1
2 # http://tinyurl.com/h47ty49
3
4
my_float
=
2.2
1
2 # http://tinyurl.com/hx9xluq
3
4
my_boolean
=
True
You can name variables whatever you’d like, as long as you follow four rules:
1. Variables can’t have spaces. If you want to use two words in a variable, put an underscore
between them: i.e., my_variable = “A string!”
2. Variable names can only contain letters, numbers, and the underscore symbol.
3. You cannot start a variable name with a number. Although you can start a variable with an
underscore, it has a special meaning that I will cover later, so avoid using it until then.
4. You cannot use Python keywords for variable names. You can find a list of keywords at
http://theselftaughtprogrammer.io/keywords .
Syntax
Syntax is the set of rules, principles, and processes that govern the structure of sentences in a given
language, specifically word order.3 The English language has syntax, and so does Python.
In Python, strings are always surrounded by quotes. This is an example of Python’s syntax. The
following is a valid Python program:
1
2 # http://tinyurl.com/j7c2npf
3
4
print
(
"Hello, World!"
)
It is valid because you followed Python’s syntax by using quotes around your text when you defined
a string. If you only used quotes on one side of your text, you would violate Python’s syntax, and
your code would not work.
Errors and Exceptions
If you write a Python program and disregard Python’s syntax, you will get one or more errors when
you run your program. The Python shell will inform you your code did not work, and it will give
you information about the error. See what happens if you try to define a string in Python with a
quote on only one side:
1
2 # http://tinyurl.com/hp2plhs
3
4
5
6 # This code has an error.
7
my_string
=
"Hello World.
3
4
5
6 # This code has an error.
10
/
0
1
2 # http://tinyurl.com/gtp6amr
3
4
5
6 # This code has an error.
7
8
y
=
2
x
=
1
Arithmetic Operators
Earlier, you used Python to do simple arithmetic calculations, like 4 / 2 . The symbols you used
in those examples are called operators . Python divides operators into several categories, and the
ones you’ve seen so far are called arithmetic operators . Here are some of the most common
arithmetic operators in Python:
When two numbers are divided there is a quotient and a remainder. The quotient is the result of the
division, and the remainder is what is left over. The modulo operator returns the remainder. For
example, 13 divided by 5 is 2 remainder 3 :
1
2 # http://tinyurl.com/grdcl95
3
4
13
/
/
5
>> 2
1
2 # http://tinyurl.com/zsqwukd
3
4
13
%
5
>> 3
When you use modulo on two numbers, if there is no remainder (modulo returns 0 ), the number is
even. If there is a remainder, the number is odd:
1
2 # http://tinyurl.com/jerpe6u
3
4
5
# even
12
%
2
>> 0
1
2 # http://tinyurl.com/gkudhcr
3
4
5
# odd
11
%
2
>> 1
There are two operators used for division. The first is //, which returns the quotient:
1
# http://tinyurl.com/hh9fqzy
2
3
4
14
/
/
3
> 4
The second is /, which returns the result of the first number divided by the second as a floating-point
number:
1
2 # http://tinyurl.com/zlkjjdp
3
4
14
/
3
> 4.666666666666667
You can raise a number by an exponentiation operator:
1
# http://tinyurl.com/h8vuwd4
2
3
2
*
*
2
>> 4
The values (in this case numbers) on either side of an operator are called operands . Together, two
operands and an operator form an expression . When your program runs, Python evaluates each
expression and returns a single value. When you type the expression 2+2 into the shell, Python
evaluates it to 4 .
The order of operations is a set of rules used in mathematical calculations to evaluate an
expression. Remember P lease E xcuse M y D ear A unt S ally? It is an acronym to help you
remember the order of operations in math equations: parentheses, exponents, multiplication,
division, addition, and subtraction. Parentheses outrank exponents, which outrank multiplication
and division, which outrank addition and subtraction. If there is a tie among operators, like in the
case of 15 / 3 × 2 , you evaluate from left to right. In this instance, the answer is the result of
15 divided by 3 times 2 . Python follows the same order of operations when it evaluates
mathematical expressions:
1
# http://tinyurl.com/hgjyj7o
2
3
4
2
+
2
*
2
>> 6
1
2 # http://tinyurl.com/hsq7rcz
3
4
(
2
+
2
)
*
2
>> 8
In the first example, 2 * 2 is evaluated first because multiplication takes precedence over
addition.
In the second example, (2+2) is evaluated first, because Python always evaluates expressions in
parentheses first.
Comparison Operators
Comparison operators are another category of operators in Python. Similar to , they are used in
expressions with operands on either side. Unlike expressions with arithmetic operators, expressions
with comparison operators evaluate to either True or False .
An expression with the > operator returns the value True if the number on the left is greater than
the number on the right, and False if it is not:
1
2 # http://tinyurl.com/jm7cxzp
3
4
100
>
10
>> True
An expression with the < operator returns the value True if the number on the left is less than the
number on the right, and False if it is not:
1
2 # http://tinyurl.com/gsdhr8q
100
<
10
>> False
An expression with the >= operator returns the value True if the number on the left is greater than
or equal to the number on the right. Otherwise, the expression returns False :
1
# http://tinyurl.com/jy2oefs
2
3
2
>
=
2
>> True
An expression with the <= operator returns the value True if the number on the left is less than or
equal to the number on the right. Otherwise, the expression returns False :
1
# http://tinyurl.com/jk599re
2
3
4
2
>
=
2
>> True
An expression with the == operator returns the value True if the two operands are equal, and
False if not:
1
# http://tinyurl.com/j2tsz9u
2
3
4
2
=
=
2
>> True
1
2 # http://tinyurl.com/j5mr2q2
3
4
1
=
=
2
>> False
An expression with the != operator returns True if the two operands are not equal, and False
otherwise:
1
2 # http://tinyurl.com/gsw3zoe
3
4
1
!
=
2
>> True
1
# http://tinyurl.com/z7pffk3
2
3
4
2
!
=
2
>> False
Earlier, you assigned variables to numbers, like x = 100 , using = . It may be tempting to read this
in your head as “x equals 100,” but don’t. As you saw earlier, = is used to assign a value to a
variable, not to check for equality. When you see x = 100 , think “x gets one hundred.” The
comparison operator == is used to test for equality, so if you see x == 100 , then think “x equals
100.”
Logical Operators
Logical operators are another category of operators in Python. Like comparison operators, logical
operators also evaluate to True or False .
The Python keyword and takes two expressions and returns True if all the expressions evaluate to
True . If any of the expressions are False , it returns False :
1
2 # http://tinyurl.com/zdqghb2
3
4
1
=
=
1
and
2
=
=
2
>> True
1
# http://tinyurl.com/zkp2jzy
2
3
4
1
=
=
2
and
2
=
=
2
>> False
1
2 # http://tinyurl.com/honkev6
3
4
1
=
=
2
and
2
=
=
1
>> False
1
# http://tinyurl.com/zjrxxrc
2
3
4
2
=
=
1
and
1
=
=
1
>> False
You can use the and keyword multiple times in one statement:
1
# http://tinyurl.com/zpvk56u
2
3
4
1
=
=
1
and
10
!
=
2
and
2
<
10
>> True
The keyword or takes two or more expressions and evaluates to True if any of the expressions
evaluate to True :
1
# http://tinyurl.com/hosuh7c
2
3
4
1
=
=
1
or
1
=
=
2
>> True
1
# http://tinyurl.com/zj6q8h9
2
3
4
1
=
=
1
or
2
=
=
2
>> True
1
2 # http://tinyurl.com/j8ngufo
3
4
1
=
=
2
or
2
=
=
1
>> False
1
# http://tinyurl.com/z728zxz
2
3
4
2
=
=
1
or
1
=
=
2
>> False
Like and , you can use multiple or keywords in one statement:
1
2 # http://tinyurl.com/ja9mech
3
4
1
=
=
1
or
1
=
=
2
or
1
=
=
3
>> True
This expression evaluates to True because 1==1 is True , even though the rest of the expressions
would evaluate to False .
Placing the keyword not in front of an expression will change the result of the evaluation to the
opposite of what it would have otherwise evaluated to. If the expression would have evaluated to
True , it will evaluate to False when preceded by not :
1
# http://tinyurl.com/h45eq6v
2
3
4
not
1
=
=
1
>> False
1
# http://tinyurl.com/gsqj6og
2
3
4
not
1
=
=
2
>> True
Conditional Statements
The keywords if , elif , and else are used in conditional statements . Conditional statements
are a type of control structure : a block of code that makes decisions by analyzing the values of
variables. A conditional statement is code that can execute additional code conditionally. Here is an
example in pseudocode (A notation resembling code used to illustrate an example) to clarify how
this works:
1
# Do not run
2
3
4
5
If (expression) Then
6
7
(code_area1)
Else
(code_area2)
This pseudocode explains that you can define two conditional statements that work together. If the
expression defined in the first conditional statement is True , all the code defined in code_area1
is executed. If the expression defined in the first conditional statement is False , all the code
defined in code_area2 is executed. The first part of the example is called an if-statement ,
and the second is called an else-statement . Together, they form an if-else statement :
a way for programmers to say “if this happens do this, otherwise, do that.” Here is an example of an
if-else statement in Python:
1
# http://tinyurl.com/htvy6g3
2
3
4
5
6 home
7 =
"America"
8
if
home
=
=
"America"
:
print
(
"Hello, America!"
)
else
:
print
(
"Hello, World!"
)
if
home
=
=
"America"
:
print
(
"Hello, America!"
)
else
:
print
(
"Hello, World!"
)
if
home
=
=
"America"
:
print
(
"Hello, America!"
)
print
(
"The number is 2."
)
if
x
%
2
=
=
0
:
print
(
"The number is even."
)
if
x
%
2
!
=
0
:
print
(
"The number is odd."
)
>> The number is 2.
>> The number is even.
Each if-statement will execute its code only if its expression evaluates to True . In this case,
the first two expressions evaluate to True , so their code executes, but the third expression
evaluates to False , so its code does not execute.
If you want to get crazy, you can even put an if-statement inside of another if-statement
(this is called nesting):
1
# http://tinyurl.com/zrodgne
2
3
4
5
6 x
7 =
10
8
9 y
10 =
11
if
x
=
=
10
:
if
y
=
=
11
:
print
(x
+
y)
>> 21
In this case, x + y will only print if the expressions in both if-statements evaluate to True .
You cannot use an else-statement on its own; they can only be used at the end of an if-
else statement .
You can use the elif keyword to create elif-statements . elif stands for else if, and
elif-statements can be indefinitely added to an if-else statement to allow it to make
additional decisions.
If an if-else statement has elif-statements in it, the if-statement expression is
evaluated first. If the expression in that statement evaluates to True , only its code is executed.
However, if it evaluates to False , each consecutive elif-statement is evaluated. As soon as
an expression in an elif-statement evaluates to True , its code is executed and no more code
executes. If none of the elif-statements evaluate to True , the code in the else-
statement is executed. Here is an example of an if-else statement with elif-
statements in it:
1
# http://tinyurl.com/jpr265j
2
3
4
5
6 home
7 =
"Thailand"
8
9 if
10 home
=
11
=
12 "Japan"
13 :
14
print
(
"Hello, Japan!"
)
elif
home
=
=
"Thailand"
:
print
(
"Hello, Thailand!"
)
elif
home
=
=
"India"
:
print
(
"Hello, India!"
)
elif
home
=
=
"China"
:
print
(
"Hello, China!"
)
else
:
print
(
"Hello, World!"
)
13
print
(
"Hello, America!"
)
elif
home
=
=
"Canada"
:
print
(
"Hello, Canada!"
)
elif
home
=
=
"Thailand"
:
print
(
"Hello, Thailand!"
)
elif
home
=
=
"Mexico"
:
print
(
"Hello, Mexico!"
)
else
:
print
(
"Hello, World!"
)
3
4
5
6 x
7 =
100
8
9 if
10 x
=
11
=
12 10
13 :
14
15 print
16 (
"10!"
17
)
18
19 elif
20 x
=
=
20
:
print
(
"20!"
)
else
:
print
(
"I don't know!"
)
if
x
=
=
100
:
print
(
"x is 100!"
)
if
x
%
2
=
=
0
:
print
(
"x is even!"
)
else
:
print
(
"x is odd!"
)
Statements
A statement is a technical term that describes various parts of the Python language. You can think
of a Python statement as a command or calculation. In this section, you will take a detailed look at
the syntax of statements. Don’t worry if some of this seems confusing at first. It will start making
more sense the more time you spend practicing Python and will help you understand several
programming concepts.
Python has two kinds of statements: simple statements and compound statements . Simple
statements can be expressed in one line of code, whereas compound statements generally span
multiple lines. Here are some examples of simple statements:
1
2 # http://tinyurl.com/jrowero
3
4
print
(
"Hello, World!"
)
1
# http://tinyurl.com/h2y549y
2
3
4
2
+
2
>> 4
if-statements , if-else statements , and the first program you wrote in this chapter
that printed Hello, World! one hundred times are all examples of compound statements.
Compound statements are made up of one or more clauses . A clause consists of two or more lines
of code: a header followed by a suite(s) . A header is a line of code in a clause that contains a
keyword, followed by a colon and a sequence of one or more lines of indented code. After the
indent, there are one or more suites. A suite is just a line of code in a clause. The header controls the
suites. Your program that prints Hello, World! a hundred times is made up of a single
compound statement:
1
# http://tinyurl.com/zfz3eel
2
3
4
for
i
in
range
(
100
):
print
(
"Hello, World!"
)
>> Hello, World!
>> Hello, World!
>> Hello, World!
…
The first line of the program is the header. It’s made up of a keyword—for —followed by a colon.
After the indentation is a suite—print(“Hello, World!”) . In this case, the header uses the
suite to print Hello, World! a hundred times. The code in this example is called a loop, which
you learn more about in Chapter 7. This code only has one clause.
A compound statement can be made up of multiple clauses. You already saw this with if-else
statements . Anytime an if-statement is followed by an else-statement , the result is
a compound statement with multiple clauses. When a compound statement has multiple clauses, the
header clauses work together. In the case of an if-else compound statement, when the if-
statement evaluates to True , the if-statement suites execute, and the else-
statement suites do not execute. When the if-statement evaluates to False , the if-
statement suites do not execute, the else-statement suites execute instead. The last
example from the previous section includes three compound statements:
1
2 # http://tinyurl.com/hpwkdo4
3
4
5
6 x
7 =
100
8
9 if
10 x
=
11
=
12 10
13 :
14
15 print
16 (
"10!"
17 )
18
19 elif
x
20
=
=
20
:
print
(
"20!"
)
else
:
print
(
"I don't know!"
)
if
x
=
=
100
:
print
(
"x is 100!"
)
if
x
%
2
=
=
0
:
print
(
"x is even!"
)
else
:
print
(
"x is odd!"
)
3
4
5
6 print
7 (
"Michael"
8 )
9
10
11
print
(
"Jordan"
)
>> Michael
>> Jordan
Vocabulary
Comment : A line (or part of a line) of code written in English (or another language) preceded by a
unique symbol telling the programming language you are using know it should ignore that line (or
part of a line) of code.
Keyword : A word with a special meaning in a programming language. You can see all of Python’s
keywords at http://theselftaughtprogrammer.io/keywords .
Data type : A category of data.
Object : A data value in Python with three properties: an identity, a data type, and a value.
Str : The data type of a string.
String : An object with the data type str . Its value is a sequence of one or more characters
surrounded by quotes.
Character : A single symbol like a or 1.
Int : The data type of whole numbers.
Integer : An object with the data type int . Its value is a whole number.
Float : The data type of decimal numbers.
Floating-point number : An object with the data type float . Its value is a decimal number.
Bool : The data type of boolean objects.
Boolean : An object with the data type bool . Its value is either True or False .
NoneType : The data type of None objects.
None : An object with the data type NoneType . Its value is always None .
Constant : A value that never changes.
Variable : A name assigned a value using the assignment operator.
Assignment operator : The = sign in Python.
Increment : Increasing the value of a variable.
Decrement : Decreasing the value of a variable.
Syntax : The set of rules, principles, and processes that govern the structure of sentences in a given
language, specifically word order.4
Syntax error : A fatal programming error caused by violating a programming language’s syntax.
Exception : A nonfatal programming error.
Operator : Symbols used with operands in an expression.
Arithmetic operator : A category of operators used in arithmetic expressions.
Operand : A value on either side of an operator.
Expression : Code with an operator surrounded by two operands.
Order of operations : A set of rules used in mathematical calculations to evaluate an expression.
Comparison operator : A category of operators used in an expression that evaluate to either True
or False .
Logical operator : A category of operators that evaluate two expressions and return either True or
False .
Conditional statement : Code that can execute additional code conditionally.
Control structure : A block of code that makes decisions by analyzing the values of variables.
Pseudocode : A notation resembling code used to illustrate an example.
if-else statement : A way for programmers to say “if this happens do this, otherwise, do that.”
if-statement : The first part of an if-else statement .
else-statement : The second part of an if-else statement .
elif-statement : Statements that can be indefinitely added to an if-else statement to allow it
to make additional decisions.
Statement : A command or calculation.
Simple statement : A statement that can be expressed in one line of code.
Compound statement : A statement that generally spans multiple lines of code.
Clause : The building blocks of compound statements. A clause is made up of two or more lines of
code: a header followed by a suite(s).
Header : A line of code in a clause containing a keyword, followed by a colon and a sequence of
one or more lines of indented code.
Suite : A line of code in a clause controlled by a header.
Challenges
1. Print three different strings.
2. Write a program that prints a message if a variable is less than 10, and different message if the
variable is greater than or equal to 10.
3. Write a program that prints a message if a variable is less than or equal to 10, another message if
the variable is greater than 10 but less than or equal to 25, and another message if the variable is
greater than 25.
4. Create a program that divides two variables and prints the remainder.
5. Create a program that takes two variables, divides them, and prints the quotient.
6. Write a program with a variable age assigned to an integer that prints different strings depending
on what integer age is.
Solutions: http://tinyurl.com/zx7o2v9 .
Chapter 4. Functions
“Functions should do one thing. They should do it well. They
should do it only.”
~ Robert C. Martin
In this chapter, you will learn about functions : compound
statements that can take input, execute instructions, and return
an output. Functions allow you to define and reuse
functionality in your programs.
Representing Concepts
From here on out, I will use a new convention (an agreed
upon way of doing things) to explain programming concepts.
Here is an example of the convention I will use:
print(“[what_you_want_to_print]”) , which
illustrates how to use the print function.
I combined Python code with brackets containing a description
to illustrate this concept. When I give an example like this,
everything is valid Python code except the brackets and the
text inside of them, which need to be replaced with valid code
when you follow the example. The text inside the brackets is a
hint for what code you should use to replace it. Python uses
brackets in its syntax, so I will use double brackets when they
should remain in your code.
Functions
Calling a function means giving the function the input it needs
to execute its instructions and return an output. Each input to a
function is a parameter . When you pass a parameter to a
function, it is called “passing” the function a parameter.
Functions in Python are similar to mathematical functions. If
you don’t remember functions from algebra, here is an
example:
1
# Do not run.
2
3
4
5
f(x)
=
x
*
2
Defining Functions
To create a function in Python you choose a function name,
define its parameters, define what it does, and define what
value the function returns. Here is the syntax for defining a
function:
1
# Do not run.
2
3
4
5
6
def
[function_name]([parameters]):
[function_definition]
3
4
5
def
f(x):
return
x
*
2
f(
2
)
3
4
5
6 # Continue from
7
8 # last example
result
=
f(
2
)
print
(result)
>> 4
You can save the result your function returns in a variable
whenever you need to use the value later in your program:
1
2 # http://tinyurl.com/znqp8fk
3
4
5
6 def
7 f(x):
8
9 return
10 x
+
11
1
12
13
14
z
=
f(
4
)
if
z
=
=
5
:
print
(
"z is 5"
)
else
:
print
(
"z is not 5"
)
>> z is 5
A function can have one parameter, multiple parameters, or no
parameters. To define a function that does not require
parameters, leave the parentheses empty when you define your
function:
1
2 # http://tinyurl.com/htk7tr6
3
4
5
6 def
7 f():
8
9 return
1
+
1
result
=
f()
print
(result)
>> 2
If you want your function to accept more than one parameter,
you must separate each parameter inside the parentheses with
a comma:
1
2 # http://tinyurl.com/gqmkft7
3
4
5
6 def
7 f(x, y, z):
8
9 return
x
+
y
+
z
result
=
f(
1
,
2
,
3
)
print
(result)
>> 6
Finally, a function does not have to include a return
statement. If a function doesn’t have a return, statement it
returns None :
1
2 # http://tinyurl.com/j8qyqov
3
4
5
6 def
7 f():
8
9 z
=
1
+
1
result
=
f()
print
(result)
>> None
Built-In Functions
Python comes with a library of functions built into the
programming language called built-in functions . They
perform all sorts of different computations and tasks and are
ready to use without any work on your part. You’ve already
seen one example of a built-in function: the first program you
wrote used the print function to print “Hello, World!”
.
len is another built-in function. It returns the length of an
object—for example, the length of a string (the number of
characters in it):
1
2 # http://tinyurl.com/zfkzqw6
3
4
len
(
"Monty"
)
>> 5
1
2 # http://tinyurl.com/h75c3cf
3
4
len
(
"Python"
)
>> 6
The built-in str function takes an object and returns a new
object with a str data type. For example, you can use str to
convert an integer to a string:
1
# http://tinyurl.com/juzxg2z
2
3
4
str
(
100
)
>> ‘100’
The int function takes an object and returns an integer
object:
1
# http://tinyurl.com/j42qhkf
2
3
4
int
(
"1"
)
>> 1
The float function takes an object and returns a floating-
point number object:
1
# http://tinyurl.com/hnk8gh2
2
3
4
float
(
100
)
>> 100.0
The parameter you pass to a str , int , or float function
must be able to become a string, integer, or a floating-point
number. The str function can accept most objects a
parameter, but the int function can only accept a string with
a number in it or a floating-point object. The float function
can only take a string with a number in it or an integer object:
1
# http://tinyurl.com/jcchmlx
2
3
4
5
6 int
7 (
"110"
8 )
9
int
(
20.54
)
float
(
"16.4"
)
float
(
99
)
>> 110
>> 20
>> 16.4
>> 99.0
Python will raise an exception if you try to pass the int or
float function a parameter it cannot convert to an integer or
a floating-point number:
1
2 # http://tinyurl.com/zseo2ls
3
4
int
(
"Prince"
)
3
4
5
6 age
7 =
input
8 (
9 "Enter your age:"
)
int_age
=
int
(age)
if
int_age <
21
:
print
(
"You are young!"
)
else
:
print
(
"Wow, you are old!"
)
Reusing Functions
Functions are not only used to compute and return values.
Functions can encapsulate functionality you want to reuse:
1
2 # http://tinyurl.com/zhy8y4m
3
4
5
6 def
7 even_odd(x):
8
9 if
10 x
%
11
2
12 =
=
0
:
print
(
"even"
)
else
:
print
(
"odd"
)
even_odd(
2
)
even_odd(
3
)
>> even
>> odd
You didn’t define a value for your function to return, but your
function is still useful. It tests if x % 2 == 0 , and prints
whether x is even or odd.
Functions allow you to write less code because you can reuse
functionality. Here is an example of a program written without
functions:
1
2 # http://tinyurl.com/jk8lugl
3
4
5
6 n
7 =
input
8 (
9 "type a number:"
)
10
11
n
12 =
13 int
(n)
14
15
16
17 if
18 n
%
19 2
20 =
=
21
0
22 :
23
24
print
25 (
26 "n is even."
)
27
else
:
print
(
"n is odd."
)
n
=
input
(
"type a number:"
)
n
=
int
(n)
if
n
%
2
=
=
0
:
print
(
"n is even."
)
else
:
print
(
"n is odd."
)
n
=
input
(
"type a number:"
)
n
=
int
(n)
if
n
%
2
=
=
0
:
print
(
"n is even."
)
else
:
print
(
"n is odd."
)
3
4
5
6 def
7 even_odd():
8
9 n
10 =
input
11
(
12 "type a number:"
13 )
14
15 n
=
int
(n)
if
n
%
2
=
=
0
:
print
(
"n is even."
)
else
:
print
(
"n is odd."
)
even_odd()
even_odd()
even_odd()
3
4
5
6 def
7 f(x
=
8 2
9 ):
return
x
*
*
x
print
(f())
print
(f(
4
))
>> 4
>> 256
First, you call your function without passing in a parameter.
Because the parameter is optional, x automatically gets 2 and
the function returns 4 .
Next, you call your function and pass in 4 as a parameter. The
function ignores the default value, x gets 4 and the function
returns 256 . You can define a function that has both required
and optional parameters, but you must define all the required
parameters before the optional ones:
1
# http://tinyurl.com/hm5svn9
2
3
4
5
6 def
7 add_it(x, y
=
8 10
9 ):
return
x
+
y
result
=
add_it(
2
)
print
(result)
>> 12
Scope
Variables have an important property called scope . When you
define a variable, its scope refers to what part of your program
can read and write to it. Reading a variable means finding its
value. Writing a variable means changing its value. A
variable’s scope is determined by where in your program it is
defined. If you define a variable outside of a function (or class,
which you learn about in Part II), the variable has a global
scope : It can be read or written to from anywhere in your
program. A variable with global scope is called a global
variable . If you define a variable inside of a function (or
class), it has local scope : your program can only read or write
to it in the function (or class) the variable was defined within.
Here are variables with global scope:
1
# http://tinyurl.com/zhmxnqt
2
3
4
5
6 x
=
1
y
=
2
z
=
3
These variables were not defined inside of a function (or
class), and therefore have a global scope. This means you can
read or write to them from anywhere—including inside of a
function:
1
# http://tinyurl.com/hgvnj4p
2
3
4
5
6 x
7 =
1
8
9 y
10 =
2
11
12
z
13 =
14 3
15
def
f():
print
(x)
print
(y)
print
(z)
f()
>> 1
>> 2
>> 3
If you define these same variables inside of a function, you
can only read or write to them from inside of that function. If
you try to access them outside of the function they were
defined in Python raises an exception:
1
# http://tinyurl.com/znka93k
2
3
4
5
6 def
7 f():
8
9 x
10 =
1
11
12
y
=
2
z
=
3
print
(x)
print
(y)
print
(z)
z
=
3
print
(x)
print
(y)
print
(z)
f()
>> 1
>> 2
>> 3
Trying to use a variable defined inside of a function outside of
it is similar to using a variable that hasn’t been defined yet,
which will cause Python to raise the same exception:
1
# http://tinyurl.com/zn8zjmr
2
3
4
5
if
x >
100
:
print
(
"x is > 100"
)
3
4
5
6 x
7 =
100
8
9
10
11 def
12 f():
13
global
x
x
+
=
1
print
(x)
f()
>> 101
Without scope, you could access every variable anywhere in
your program, which would be problematic. If you have a
large program, and you write a function that uses the variable
x , you might accidently change the value of a variable also
called x that you previously defined elsewhere in your
program. Mistakes like that can alter the behavior of your
program and may cause errors or unexpected results. The
larger your program gets, and the more variables it has, the
more likely this becomes.
Exception Handling
Relying on user input from the input function means you do
not control the input to your program—the user does, and that
input could cause an error. For example, say you write a
program that collects two numbers from a user and prints the
result of the first number divided by the second number:
1
2 # http://tinyurl.com/jcg5qwp
3
4
5
6 a
7 =
input
8 (
"type a number:"
)
b
=
input
(
"type another:"
)
a
=
int
(a)
b
=
int
(b)
print
(a
/
b)
>> type a number:
>> 10
>> type another:
>> 5
>> 2
Your program appears to work. However, you will run into a
problem if the user inputs 0 as the second number:
1
# http://tinyurl.com/ztpcjs4
2
3
4
5
6 a
7 =
input
8 (
"type a number:"
)
b
=
input
(
"type another:"
)
a
=
int
(a)
b
=
int
(b)
print
(a
/
b)
>> type a number:
>> 10
>> type another:
>> 0
>> ZeroDivisionError: integer division
or modulo by zero
You cannot just hope someone using this program will not
enter 0 as the second number. One way to solve this is to use
exception handling , which allows you to test for error
conditions, “catch” exceptions if they occur, and decide how
to proceed.
The keywords try and except are used for exception
handling. When you change this program to use exception
handling, if a user enters 0 as the second number, instead of
raising an exception, the program could print a message telling
them not to enter 0 .
Each exception in Python is an object, so you can use them in
your programs. You can see a list of built-in exceptions here:
https://www.tutorialspoint.com/python/standard_exceptions.ht
m . If you are in a situation where you think your code may
raise an exception, use a compound statement with the
keywords try and except to catch it.
The try clause contains the error that could occur. The
except clause contains code that will only execute if the
exception in your try clause occurs. Here is an example of
how you can use exception handling in your program, so if a
user enters 0 as the second number, your program doesn’t
break:
1
# http://tinyurl.com/j2scn4f
2
3
4
5
6 a
7 =
input
8 (
9 "type a number:"
)
10
11
b
=
input
(
"type another:"
)
a
=
int
(a)
b
=
int
(b)
try
:
print
(a
/
b)
except
ZeroDivisionError:
print
(
"b cannot be zero."
)
a
=
int
(a)
b
=
int
(b)
try
:
print
(a
/
b)
except
ZeroDivisionError:
print
(
"b cannot be zero."
)
3
4
5
6 try
7 :
8
9 a
10 =
input
11
(
12 "type a number:"
)
b
=
input
(
"type another:"
)
a
=
int
(a)
b
=
int
(b)
print
(a
/
b)
except
(ZeroDivisionError,
ValueError):
print
(
"Invalid input."
)
3
4
5
6 try
7 :
10
/
0
c
=
"I will never get defined."
except
ZeroDivisionError:
print
(c)
Docstrings
When you define a function with parameters, sometimes the
parameters have to be a particular data type for the function to
work. How do you communicate this to whoever calls your
function? When you write a function, it is good practice to
leave a comment called a docstring at the top of the function
explaining what data type each parameter needs to be.
Docstrings explain what the function does, and document what
kinds of parameters it needs:
1
2 # http://tinyurl.com/zhahdcg
3
4
5
6 def
7 add(x, y):
8
9 """
10
11
Returns x + y.
:param x: int.
:param y: int.
"""
return
x
+
y
The first line of the docstring clearly explains what your
function does, so when other developers reuse your function or
method, they do not have to read through all of your code to
figure out its purpose. The rest of the docstring’s lines list the
function’s parameters, the parameter types, and what it returns.
Docstrings will help you program faster because you can read
a docstring to figure out what a function does, instead of
reading all the code. To keep the examples in this book
concise, I’ve omitted docstrings I would usually include.
Normally when I write code, I include docstrings to make my
code easy to understand for everyone who reads it in the
future.
1
2 # http://tinyurl.com/zptktex
3
4
5
x
=
100
print
(x)
>> 100
Instead, pass the integer directly to the print function:
1
2 # http://tinyurl.com/hmwr4kd
3
4
print
(
100
)
>> 100
I violate this rule in many examples in this book to make what
I’m doing easy for you to understand. You don’t need to do the
same when you are writing code.
Vocabulary
Functions : Compound statements that can take input, execute
instructions, and return an output.
Convention : An agreed upon way of doing things.
Calling : Giving the function the input it needs to execute its
instructions and return an output.
Parameter : Data passed into a function.
Required parameter : A non-optional parameter.
Optional parameter : An optional parameter.
Built-in function : A function that comes with Python.
Scope : Where a variable can be read or written to.
Global scope : The scope of a variable that can be read or
written to from anywhere in a program.
Global variable : A variable with a global scope.
Local scope : The scope of a variable that can only be read or
written to from the function (or class) the variable was defined
within.
Exception handling : A programming concept that allows you
to test for error conditions, “catch” exceptions if they occur,
and decide how to proceed.
Docstring : Docstrings explain what a function does, and
documents what kinds of parameters it takes.
Challenges
1. Write a function that takes a number as an input and returns
that number squared.
2. Create a function that accepts a string as a parameter and
prints it.
3. Write a function that takes three required parameters and
two optional parameters.
4. Write a program with two functions. The first function
should take an integer as a parameter and return the result of
the integer divided by 2. The second function should take an
integer as a parameter and return the result of the integer
multiplied by 4. Call the first function, save the result as a
variable, and pass it as a parameter to the second function.
5. Write a function that converts a string to a float and
returns the result. Use exception handling to catch the
exception that could occur.
6. Add a docstring to all of the functions you wrote in
challenges 1–5.
Solutions: http://tinyurl.com/hkzgqrv .
Chapter 5. Containers
“The fool wonders, the wise man asks.”
~ Benjamin Disraeli
In Chapter 3, you learned how to store objects in variables. In
this chapter, you find out how to store objects in containers.
Containers are like filing cabinets: they keep your data
organized. You will learn three commonly used containers:
lists, tuples, and dictionaries.
Methods
In Chapter 4, you learned about functions. Python has a
similar concept called methods . Methods are functions
closely associated with a given type of data. Methods execute
code and can return a result just like a function. Unlike a
function, you call a method on an object. You can also pass
them parameters. Here is an example of calling the methods
upper and replace on a string:
1
# http://tinyurl.com/zdllght
2
3
4
"Hello"
.upper()
>> ‘HELLO’
1
# http://tinyurl.com/hfgpst5
2
3
4
"Hello"
.replace(
"o"
,
"@"
)
>> ‘Hell@’
You will learn more about methods in Part II.
Lists
A list is a container that stores objects in a specific order.
3
4
5
fruit
=
list
()
fruit
>> []
Or, with brackets:
1
2 # http://tinyurl.com/jft8p7x
3
4
5
fruit
=
[]
fruit
>> []
You can create a list with items already in it by using the
second syntax [] , and placing each item you want in the list
inside the brackets, separated by commas:
1
2 # http://tinyurl.com/h2y8nos
3
4
5
fruit
=
[
"Apple"
,
"Orange"
,
"Pear"
]
fruit
fruit.append(
"Banana"
)
fruit.append(
"Peach"
)
fruit
3
4
5
6 random
7 =
[]
8
9 random.append(
True
)
random.append(
100
)
random.append(
1.1
)
random.append(
"Hello"
)
random
1
2 # http://tinyurl.com/z8zzk8d
3
4
fruit
=
[
"Apple"
,
"Orange"
,
"Pear"
]
You can retrieve an item with its index using the syntax
[list_name][[index]]:
1
2 # http://tinyurl.com/jqtlwpf
3
4
5
6 fruit
7 =
[
"Apple"
,
"Orange"
,
"Pear"
]
fruit[
0
]
fruit[
1
]
fruit[
2
]
>> ‘Apple’
>> ‘Orange’
>> ‘Pear’
If you try to access an index that doesn’t exist, Python raises
an exception:
1
2 # http://tinyurl.com/za3rv95
3
4
5
colors
=
[
"blue"
,
"green"
,
"yellow"
]
colors[
4
]
3
4
5
6 colors
7 =
[
"blue"
,
"green"
,
"yellow"
]
colors
colors[
2
]
=
"red"
colors
3
4
5
6 colors
7 =
[
8 "blue"
,
"green"
,
"yellow"
]
colors
item
=
colors.pop()
item
colors
3
4
5
6 colors1
=
[
"blue"
,
"green"
,
"yellow"
]
colors2
=
[
"orange"
,
"pink"
,
"black"
]
colors1
+
colors2
"green"
in
colors
>> True
Use the keyword not to check if an item is not in a list:
1
# http://tinyurl.com/jqzk8pj
2
3
4
5
colors
=
[
"blue"
,
"green"
,
"yellow"
]
"black"
not
in
colors
>> True
You can get the size of a list (the number of items in it) with
the len function:
1
2 # http://tinyurl.com/hhx6rx4
3
4
len
(colors)
>> 3
Here is an example of how you might use a list in practice:
1
# http://tinyurl.com/gq7yjr7
2
3
4
5
6 colors
7 =
[
8 "purple"
9 ,
10
11
"orange"
12 ,
13
14
"green"
15 ]
guess
=
input
(
"Guess a color:"
)
if
guess
in
colors:
print
(
"You guessed correctly!"
)
else
:
print
(
"Wrong! Try again."
)
Tuples
A tuple is a container that stores objects in a specific order.
Unlike lists, tuples are immutable , which means their
contents cannot change. Once you create a tuple, you cannot
modify the value of any of the items in it, add new items to it,
or remove items from it. You represent tuples with
parentheses. You must separate items in a tuple with commas.
There are two syntaxes to create a tuple:
1
2 # http://tinyurl.com/zo88eal
3
4
5
my_tuple
=
tuple
()
my_tuple
>> ()
And:
1
# http://tinyurl.com/zm3y26j
2
3
4
5
my_tuple
=
()
my_tuple
>> ()
To add objects to a tuple, create one with the second syntax
with each item you want to add, separating them with
commas:
1
2 # http://tinyurl.com/zlwwfe3
3
4
5
rndm
=
(
"M. Jackson"
,
1958
,
True
)
rndm
3
4
5
6 # this is a tuple
7
8 (
"self_taught"
9 ,)
(
9
)
+
1
>> (‘self_taught’,)
>> 10
You cannot add new items to a tuple or change it once you’ve
created it. If you try to change an object in a tuple after you’ve
created it, Python will raise an exception:
1
2 # http://tinyurl.com/z3x34nk
3
4
5
6 dys
7 =
(
8 "1984"
9 ,
"Fahrenheit 451"
)
dys[
1
]
=
"Handmaid's Tale"
3
4
5
6 dys
7 =
(
8 "1984"
9 ,
"Fahrenheit 451"
)
dys[
2
]
"Fahrenheit 451"
)
"1984"
in
dys
>> True
Put the keyword not before in to check if an item is not in a
tuple:
1
# http://tinyurl.com/jpdjjv9
2
3
4
5
6 dys
7 =
(
8 "1984"
9 ,
"Fahrenheit 451"
)
"Handmaid's Tale"
not
in
dys
>> True
You may be wondering why you would want to use a data
structure that appears to be a less flexible list. Tuples are
useful when you are dealing with values you know will never
change, and you want to ensure other parts of your program
won’t change them. Geographic coordinates are an example of
data that is useful to store in a tuple. You should store the
longitude and latitude of a city in a tuple because those values
are never going to change and storing the data in a tuple
ensures other parts of your program can’t accidentally change
them. Tuples—unlike lists—can be used as keys in
dictionaries, which you will learn about in the next section of
this chapter.
Dictionaries
Dictionaries are another built-in container for storing objects.
They are used to link one object, called a key , to another
object—called the value . Linking one object to another is
called mapping . The result is a key-value pair . You add
key-value pairs to a dictionary. You can then look up a key in
the dictionary and get its value. You cannot, however, use a
value to look up a key.
Dictionaries are mutable, so you can add new key-value pairs
to them. Unlike lists and tuples, dictionaries do not store
objects in a specific order. Their usefulness relies on the
associations formed between keys and values, and there are
many situations where you need to store data in pairs. For
example, you could store information about someone in a
dictionary. You could map a key called height to a value
representing the person’s height, a key called eyecolor to a
value representing the person’s eye color and a key called
nationality to a value representing the person’s nationality.
3
4
5
my_dict
=
dict
()
my_dict
>> {}
And:
1
2 # http://tinyurl.com/jfgemf2
3
4
5
my_dict
=
{}
my_dict
>> {}
You can add key-value pairs to a dictionary when you create it.
Both syntaxes have the key separated from the value by a
colon. A comma must separate each key-value pair. Unlike a
tuple, if you have just one key-value pair, you do not need a
comma after it. Here is how you add key-value pairs to a
dictionary when you create it:
1
2 # http://tinyurl.com/hplqc4u
3
4
5
6 fruits
7 =
{
8 "Apple"
:
"Red"
,
"Banana"
:
"Yellow"
}
fruits
3
4
5
6 facts
7 =
dict
8 ()
9
10
11
12 # add a value
13
facts[
14
"code"
15 ]
16 =
"fun"
17
18 # look up a key
19
20 facts[
"code"
21 ]
22
# add a value
facts[
"Bill"
]
=
"Gates"
# look up a key
facts[
"Bill"
]
# add a value
facts[
"founded"
]
=
1776
# look up a key
facts[
"founded"
]
>> ‘fun’
>> Gates
>> 1776
Any object can be a dictionary value. In the previous example,
the first two values are strings, and the last value, 1776 , is an
integer.
Unlike a dictionary value, a dictionary key must be immutable.
A string or a tuple can be a dictionary key, but not a list or a
dictionary.
Use the in keyword to check if a key is in a dictionary. You
cannot use the in keyword to check if a value is in a
dictionary:
1
2 # http://tinyurl.com/hgf9vmp
3
4
5
6 bill
7 =
dict
8 ({
"Bill Gates"
:
"charitable"
})
"Bill Gates"
in
bill
>> True
If you try to access a key that isn’t in a dictionary, Python will
raise an exception.
Add the keyword not to in to check if a key is not in a
dictionary:
1
# http://tinyurl.com/he3g993
2
3
4
5
6 bill
7 =
dict
8 ({
"Bill Gates"
:
"charitable"
})
"Bill Doors"
not
in
bill
>> True
You can delete a key-value pair from a dictionary with the
keyword del :
1
2 # http://tinyurl.com/htrd9lj
3
4
5
6 books
7 =
{
8 "Dracula"
9 :
"Stoker"
10
,
11
"1984"
:
"Orwell"
,
"The Trial"
:
"Kafka"
}
del
books[
"The Trial"
]
books
3
4
5
6 rhymes
7 =
{
8 "1"
9 :
"fun"
10
,
11
12
13 "2"
:
14 "blue"
15 ,
16
17 "3"
:
"me"
,
"4"
:
"floor"
,
"5"
:
"live"
n
=
input
(
"Type a number:"
)
if
n
in
rhymes:
rhyme
=
rhymes[n]
print
(rhyme)
else
:
print
(
"Not found."
)
Type a number:
Your dictionary (rhymes ) has six song names (keys) mapped
to six musicians (values). You ask the user to type the name of
a song and save their response in a variable. Before you look
up their response in your dictionary, check to make sure the
key exists using the in keyword. If the key exists, you look up
the name of the song in your dictionary and print the name of
the artist who sings it. Otherwise, you print a message letting
the user know the name of the song is not available.
Containers in Containers
You can store containers in other containers. For example, you
can store lists in a list:
1
2 # http://tinyurl.com/gops9fz
3
4
5
6 lists
7 =
[]
8
9 rap
10 =
[
11
"Kanye West"
12 ,
13
14
"Jay Z"
15 ,
16
17
"Eminem"
18
,
19
20
21 "Nas"
]
22
23
24
25 rock
=
[
"Bob Dylan"
,
"The Beatles"
,
"Led Zeppelin"
]
djs
=
[
"Zeds Dead"
,
"Tiesto"
]
lists.append(rap)
lists.append(rock)
lists.append(djs)
print
(lists)
1
# http://tinyurl.com/gu4mudk
2
3
4
5
6 # Continue from
7
8 # last example
rap
=
lists[
0
]
print
(rap)
1
2 # http://tinyurl.com/hdtosm2
3
4
5
6 # Continue from
7
8 # last example
9
10
11
rap
=
lists[
0
]
rap.append(
"Kendrick Lamar"
)
print
(rap)
print
(lists)
chicago
=
(
41.8781
,
87.6298
)
locations.append(la)
locations.append(chicago)
print
(locations)
nines
=
[
"Hemingway"
,
"Fitzgerald"
,
"Orwell"
]
authors
=
(eights, nines)
print
(authors)
"Fitzgerald"
:
"9.24.1896"
}
my_list
=
[bday]
print
(my_list)
my_tuple
=
(bday,)
print
(my_tuple)
3
4
5
6 ny
7 =
{
8 "location"
9 :
10
11
(
12 40.7128
13 ,
14
15 74.0059
16 ),
17
18
19
"celebs"
:
[
"W. Allen"
,
"Jay Z"
,
"K. Bacon"
],
"facts"
:
{
"state"
:
"NY"
,
"country"
:
"America"
}
Vocabulary
Method : Functions closely associated with a given type of
data.
List : A container that stores objects in a specific order.
Iterable : An object is iterable when you can access each item
using a loop.
Iterables : Objects that are iterable like strings, lists, and
tuples.
Index : A number representing a position in an iterable.
Mutable : When a container is mutable the contents of the
container can change.
Immutable : When a container is immutable the contents of
the container cannot change.
Dictionary : A built-in container for storing objects used to
map one object—called a key—to another object—called the
value.
Key : A value used to look up a value in a dictionary.
Value : A value mapped to a key in a dictionary.
Mapping : Linking one object to another.
Key-value pair : A key mapped to a value in a dictionary.
Challenges
1. Create a list of your favorite musicians.
2. Create a list of tuples, with each tuple containing the
longitude and latitude of somewhere you’ve lived or visited.
3. Create a dictionary that contains different attributes about
you: height, favorite color, favorite author, etc.
4. Write a program that lets the user ask your height, favorite
color, or favorite author, and returns the result from the
dictionary you created in the previous challenge.
5. Create a dictionary mapping your favorite musicians to a list
of your favorite songs by them.
6. Lists, tuples, and dictionaries are just a few of the containers
built into Python. Research Python sets (a type of container).
When would you use a set?
Solutions: http://tinyurl.com/z54w9cb .
Chapter 6. String Manipulation
“In theory, there is no difference between theory and practice.
But, in practice, there is.”
~ Jan L. A. van de Snepscheut
Python has built-in functionality for manipulating strings, such
as splitting a string into two parts at a given character or
changing a string’s case. For example, if you have a string IN
ALL CAPS, and you want it to be all lowercase, you can
change its case using Python. In this chapter, you will learn
more about strings and go over some of Python’s most useful
tools for manipulating them.
Triple Strings
If a string spans more than one line, you have to put it in triple
quotes:
1
2 # http://tinyurl.com/h59ygda
3
4
5
6 """ line one
7
line two
line three
"""
If you try to define a string that spans more than one line with
single or double quotes, you will get a syntax error.
Indexes
Strings, like lists and tuples, are iterable. You can look up each
character in a string with an index. Like other iterables, the
first character in a string is at index 0 , and each subsequent
index is incremented by 1 :
1
2 # http://tinyurl.com/zqqc2jw
3
4
5
6 author
7 =
"Kafka"
8
9 author[
0
]
author[
1
]
author[
2
]
author[
3
]
author[
4
]
>> ‘K’
>> ‘a’
>> ‘f’
>> ‘k’
>> ‘a’
In this example, you used the indexes 0 , 1 , 2 , 3 , and 4 to
look up each of the characters in the string “Kafka” . If you
try to look up a character past the last index in your string,
Python raises an exception:
1
2 # http://tinyurl.com/zk52tef
3
4
5
author
=
"Kafka"
author[
5
]
author[
-
1
]
>> a
The negative index -2 looks up the second to last item, the
negative index -3 looks up the item third to last, and so on:
1
2 # http://tinyurl.com/jtpx7sr
3
4
5
6 author
=
"Kafka"
author[
-
2
]
author[
-
3
]
>> k
>> f
3
4
5
6 ff
=
"F. Fitzgerald"
ff
=
"F. Scott Fitzgerald"
ff
Concatenation
You can add two (or more) strings together using the addition
operator. The result is a string made up of the characters from
the first string, followed by the characters from the next
string(s). Adding strings together is called concatenation:
1
2 # http://tinyurl.com/h4z5mlg
3
4
"cat"
+
"in"
+
"hat"
> ‘catinhat’
1
2 # http://tinyurl.com/gsrajle
3
4
"cat "
+
" in"
+
" the"
+
" hat"
String Multiplication
You can multiply a string by a number with the multiplication
operator:
1
2 # http://tinyurl.com/zvm9gng
3
4
"Sawyer"
*
3
>> SawyerSawyerSawyer
Change Case
You can change every character in a string to uppercase by
calling the upper method on it:
1
2 # http://tinyurl.com/hhancz6
3
4
3
4
"SO IT GOES."
.lower()
1
2 # http://tinyurl.com/jp5hexn
3
4
Format
You can create a new string using the format method, which
looks for occurrences of curly brackets {} in the string, and
replaces them with the parameters you pass in:
1
2 # http://tinyurl.com/juvguy8
3
4
"William {}"
.
format
(
"Faulkner"
)
1
2 # http://tinyurl.com/zcpt9se
3
4
5
last
=
"Faulkner"
"William {}"
.
format
(last)
3
4
5
6 author
7 =
"William Faulkner"
8
9 year_born
10 =
"1897"
.
format
(author,
year_born)
adj
=
input
(
"Enter an adj:"
)
n2
=
input
(
"Enter a noun:"
)
r
=
"""The {} {} the {} {}
"""
.
format
(n1,
v,
adj,
n2)
print
(r)
Split
Strings have a method called split , which you can use to
separate one string into two or more strings. You pass the
split method a string as a parameter, and it uses that string
to divide the original string into multiple strings. For example,
you can separate the string “I jumped over the
puddle. It was 12 feet!” into two different strings
by passing the split method a period as a parameter:
1
2 # http://tinyurl.com/he8u28o
3
4
"Hello.Yes!"
.split(".")
Join
The join method lets you add new characters between every
character in a string:
1
# http://tinyurl.com/h2pjkso
2
3
4
5
6 first_three
=
"abc"
result
=
"+"
.join(first_three)
result
>> ‘a+b+c’
You can turn a list of strings into a single string by calling the
join method on an empty string, and passing in the list as a
parameter:
1
2 # http://tinyurl.com/z49e3up
3
4
5
6 words
7 =
[
8 "The"
9 ,
10
11
"fox"
12 ,
"jumped"
,
"over"
,
"the"
,
"fence"
,
"."
]
one
=
"".join(words)
one
>> Thefoxjumpedoverthefence.
You can create a string with each word separated by a space by
calling the join method on a string with a space in it:
1
2 # http://tinyurl.com/h4qq5oy
3
4
5
6 words
7 =
[
8 "The"
9 ,
10
11
"fox"
12 ,
"jumped"
,
"over"
,
"the"
,
"fence"
,
"."
]
one
=
" "
.join(words)
one
Strip Space
You can use the strip method to remove leading and trailing
whitespace from a string:
1
2 # http://tinyurl.com/jfndhgx
3
4
5
6 s
=
" The "
s
=
s.strip()
>> ‘The’
Replace
The replace method replaces every occurrence of a string
with another string. The first parameter is the string to replace,
and the second parameter is the string to replace the
occurrences with:
1
2 # http://tinyurl.com/zha4uwo
3
4
5
6 equ
=
"All animals are equal."
equ
=
equ.replace(
"a"
,
"@"
)
print
(equ)
Find an Index
You can get the index of the first occurrence of a character in a
string with the index method. Pass in the character you are
looking for as a parameter, and the index method returns the
index of the first occurrence of that character in the string:
1
2 # http://tinyurl.com/hzc6asc
3
4
"animals"
.index(
"m"
)
>> 3
Python raises an exception if the index method does not find
a match:
1
2 # http://tinyurl.com/jmtc984
3
4
"animals"
.index(
"z"
)
"animals"
.index(
"z"
)
except
:
print
(
"Not found."
)
In
The in keyword checks if a string is in another string, and
returns either True or False :
1
# http://tinyurl.com/hsnygwz
2
3
4
"Cat"
in
"Cat in the hat."
>> True
1
2 # http://tinyurl.com/z9b3e97
3
4
"Bat"
in
"Cat in the hat."
>> False
Put the keyword not in front of the in to check if one string
is not in another string:
1
2 # http://tinyurl.com/jz8sygd
"Potter"
not
in
"Harry"
>> True
Escaping Strings
If you use quotes inside a string, you will get a syntax error:
1
2 # http://tinyurl.com/zj6hc4r
3
4
5
6 # this code does not work.
7
3
4
1
# http://tinyurl.com/zr7o7d7
2
3
4
3
4
1
2 # http://tinyurl.com/zkgfawo
3
4
Newline
Putting \n inside a string represents a newline:
1
2 # http://tinyurl.com/zyrhaeg
3
4
print
(
"line1\nline2\nline3"
)
>> line1
>> line2
>> line3
Slicing
Slicing is a way to return a new iterable from a subset of the
items in another iterable. The syntax for slicing is
[iterable][[start_index:end_index]] . The
start index is the index to start slicing from, and the end
index is the index to stop slicing at.
Here is how to slice a list:
1
2 # http://tinyurl.com/h2rqj2a
3
4
5
6 fict
7 =
[
8 "Tolstoy"
9 ,
"Camus"
,
"Orwell"
,
"Huxley"
,
"Austin"
]
fict[
0
:
3
]
1
2 # http://tinyurl.com/hug9euj
3
4
5
6 ivan
7 =
"""In place of death there \
8
9 was light."""
ivan[
0
:
17
]
ivan[
17
:
33
]
1
# http://tinyurl.com/judcpx4
2
3
4
5
6 ivan
7 =
"""In place of death there \
8
was light."""
ivan[:
17
]
was light."""
ivan[
17
:]
3
4
5
6 ivan
7 =
"""In place of death there \
8
was light."""
ivan[:]
Vocabulary
Negative index : An index (that must be a negative number)
you can use to look up items in an iterable from right to left,
instead of left to right.
Escaping : Putting a symbol in front of a character that
normally has a special meaning in Python, which lets Python
know that, in this instance, the character is meant to represent
a character, and not the special meaning.
Slicing : A way to return a new iterable from a subset of the
items in another iterable.
Start index : The index to start slicing from.
End index : The index to stop slicing at.
Challenges
1. Print every character in the string “Camus”.
2. Write a program that collects two strings from a user, inserts
them into the string “Yesterday I wrote a
[response_one]. I sent it to
[response_two]!” and prints a new string.
3. Use a method to make the string “aldous Huxley was born
in 1894.” grammatically correct by capitalizing the first letter
in the sentence.
4. Take the string “Where now? Who now? When
now?” and call a method that returns a list that looks like:
[“Where now?”, “Who now?”, “When now?”] .
5. Take the list [“The”, “fox”, “jumped”,
“over”, “the”, “fence”, “.”] and turn it into a
grammatically correct string. There should be a space between
each word, but no space between the word fence and the
period that follows it. (Don’t forget, you learned a method that
turns a list of strings into a single string.)
6. Replace every instance of “s” in “A screaming
comes across the sky.” with a dollar sign.
7. Use a method to find the first index of the character “m” in
the string “Hemingway” .
8. Find dialogue in your favorite book (containing quotes) and
turn it into a string.
9. Create the string “three three three” using
concatenation, and then again using multiplication.
10. Slice the string “It was a bright cold day in
April, and the clocks were striking
thirteen.” to only include the characters before the
comma.
Solutions: http://tinyurl.com/hapm4dx .
Chapter 7. Loops
“Eighty percent of success is showing up.”
—Woody Allen
The second program I introduced in this book printed Hello,
World! a hundred times. It accomplished this using a loop
: a piece of code that continually executes instructions until a
condition defined in the code is satisfied. In this chapter, you
will learn about loops and how to use them.
For-Loops
In this section, you will learn how to use a for-loop : a loop
used to iterate through an iterable. This process is called
iterating. You can use a for-loop to define instructions that
execute once for every item in an iterable, and you can access
and manipulate each item in the iterable from within the
instructions you defined. For example, you could use a for-
loop to iterate through a list of strings, and use the upper
method to print each string with all of its characters
capitalized.
You can define a for-loop using the syntax for
[variable_name] in [iterable_name]:
[instructions] where [variable_name] is a
variable name of your choosing assigned to the value of each
item in the iterable, and [instructions] is the code to be
executed each time through the loop. Here is an example using
a for-loop to iterate through the characters of a string:
1
# http://tinyurl.com/jya6kpm
2
3
4
5
6 name
=
"Ted"
for
character
in
name:
print
(character)
>> T
>> e
>> d
Each time around the loop, the variable character gets
assigned to an item in the iterable name . The first time
around the loop, T prints because the variable character is
assigned the value of the first item in the iterable name . The
second time around the loop, e prints because the variable
character is assigned the value of the second item in the
iterable name . This process continues until every item in the
iterable has been assigned to the variable character .
Here is an example using a for-loop to iterate through the
items in a list:
1
2 # http://tinyurl.com/zeftpq8
3
4
5
6 shows
7 =
[
8 "GOT"
,
"Narcos"
,
"Vice"
]
for
show
in
shows:
print
(show)
>> GOT
>> Narcos
>> Vice
An example using a for-loop to iterate through the items in
a tuple:
1
2 # http://tinyurl.com/gpr5a6e
3
4
5
6 coms
7 =
(
8 "A. Development"
,
"Friends"
,
"Always Sunny"
)
for
show
in
coms:
print
(show)
>> A. Development
>> Friends
>> Always Sunny
And an example using a for-loop to iterate through the
keys in a dictionary:
1
# http://tinyurl.com/jk7do9b
2
3
4
5
6 people
7 =
{
8 "G. Bluth II"
9 :
10
11
"A. Development"
12 ,
13
14
"Barney"
:
"HIMYM"
,
"Dennis"
:
"Always Sunny"
}
for
character
in
people:
print
(character)
>> Dennis
>> Barney
>> G. Bluth II
You can use for-loops to change the items in a mutable
iterable, like a list:
1
2 # http://tinyurl.com/j8wvp8c
3
4
5
6 tv
7 =
[
8 "GOT"
9 ,
10
11
"Narcos"
12 ,
13
14
"Vice"
15 ]
i
=
0
for
show
in
tv:
new
=
tv[i]
new
=
new.upper()
tv[i]
=
new
i
+
=
1
print
(tv)
3
4
5
6 tv
7 =
[
8 "GOT"
9 ,
"Narcos"
10
,
11
12
"Vice"
]
for
i, show
in
enumerate
(tv):
new
=
tv[i]
new
=
new.upper()
tv[i]
=
new
print
(tv)
3
4
5
6 tv
7 =
[
8 "GOT"
9 ,
"Narcos"
10
,
11
12
13 "Vice"
]
14
15 coms
16 =
[
17 "Arrested Development"
18 ,
19
20
"friends"
21 ,
22
"Always Sunny"
]
all_shows
=
[]
for
show
in
tv:
show
=
show.upper()
all_shows.append(show)
for
show
in
coms:
show
=
show.upper()
all_shows.append(show)
print
(all_shows)
Range
You can use the built-in range function to create a sequence
of integers, and use a for-loop to iterate through them. The
range function takes two parameters: a number where the
sequence starts and a number where the sequence stops. The
sequence of integers returned by the range function includes
the first parameter (the number to start at), but not the second
parameter (the number to stop at). Here is an example of using
the range function to create a sequence of numbers, and
iterate through them:
1
# http://tinyurl.com/hh5t8rw
2
3
4
5
for
i
in
range
(
1
,
11
):
print
(i)
>> 1
…
>> 9
>> 10
In this example, you used a for-loop to print each number
in the iterable returned by the range function. Programmers
often name the variable used to iterate through a list of
integers i .
While-Loops
In this section, you will learn how to use a while-loop : a
loop that executes code as long as an expression evaluates to
True . The syntax for a while-loop is while
[expression]: [code_to_execute] , where
[expression] represents the expression that determines
whether or not the loop will continue and
[code_to_execute] represents the code the loop should
execute as long as it does:
1
# http://tinyurl.com/j2gwlcy
2
3
4
5
6 x
7 =
10
8
while
x >
0
:
print
(
'{}'
.
format
(x))
x
-
=
1
print
(
"Happy New Year!"
)
>> 10
>> 9
>> 8
>> 7
>> 6
>> 5
>> 4
>> 3
>> 2
>> 1
>> Happy New Year!
Your while-loop executes its code as long as the
expression you defined in its header, x > 0 , evaluates to
True . The first time around the loop x is 10 , and the
expression x > 0 evaluates to True . Your while-loop
code prints the value of x , then decrements x by 1 . x now
equals 9 . The next time around the loop x is printed again,
and gets decremented to 8 . This process continues until x is
decremented to 0 , at which point x > 0 evaluates to False
, and your loop ends. Python then executes the next line of
code after your loop, and prints Happy New Year!
If you define a while-loop with an expression that always
evaluates to True , your loop will run forever. A loop that
never ends is called an infinite loop . Here is an example of an
infinite loop (be prepared to press control-c on your keyboard
in the Python shell to stop the infinite loop from running):
1
2 # http://tinyurl.com/hcwvfk8
3
4
5
while
True
:
print
(
"Hello, World!"
)
Break
You can use a break-statement —a statement with the
keyword break — to terminate a loop. The following loop
will run one hundred times:
1
2 # http://tinyurl.com/zrdh88c
3
4
5
for
i
in
range
(
0
,
100
):
print
(i)
>> 0
>> 1
…
If you add a break-statement , the loop only runs once:
1
2 # http://tinyurl.com/zhxf3uk
3
4
5
6 for
i
in
range
(
0
,
100
):
print
(i)
break
>> 0
As soon as Python hits the break-statement , the loop
ends. You can use a while-loop and the break keyword
to write a program that keeps asking the user for input until
they type q to quit:
1
2 # http://tinyurl.com/jmak8tr
3
4
5
6 qs
7 =
[
8 "What is your name?"
9 ,
10
11
"What is your fav. color?"
12 ,
13
n
=
0
while
True
:
print
(
"Type q to quit"
)
a
=
input
(qs[n])
if
a
=
=
"q"
:
break
n
=
(n
+
1
)
%
3
Type q to quit
What is your name?
Each time through the loop, your program asks the user one of
the questions in your qs list.
n is an index variable. Each time around the loop, you assign
n to the evaluation of the expression (n + 1) % 3 , which
enables you to cycle indefinitely through every question in
your qs list. The first time around the loop, n starts at 0 .
Next, n is assigned the value of the expression (0 + 1) %
3 , which evaluates to 1 . Then, n is assigned to the value of
(1 + 1) % 3 , which evaluates to 2 , because whenever the
first number in an expression using modulo is smaller than the
second, the answer is the first number. Finally, n is assigned
the value of (2 + 1) % 3 , which evaluates back to 0 .
Continue
You can use a continue-statement —a statement with
the keyword continue — to stop the current iteration of a
loop and move on to the next iteration of it. Say you want to
print all the numbers from 1 to 5 , except the number 3 . You
can achieve this using a for-loop and a continue-
statement :
1
# http://tinyurl.com/hflun4p
2
3
4
5
6 for
7 i
in
range
(
1
,
6
):
if
i
=
=
3
:
continue
print
(i)
>> 1
>> 2
>> 4
>> 5
In this loop, when i equals 3 , your continue-
statement executes, and instead of causing your loop to
exit completely—like the break keyword would—the loop
persists. The loop moves on to the next iteration, skipping any
code that would have executed. When i equals 3 , and Python
executes the continue-statement , Python does not
print the number 3 .
You can achieve the same result using a while-loop and a
continue-statement :
1
2 # http://tinyurl.com/gp7forl
3
4
5
6 i
7 =
1
8
9 while
10 i <
=
5
:
if
i
=
=
3
:
i
+
=
1
continue
print
(i)
i
+
=
1
>> 1
>> 2
>> 4
>> 5
Nested Loops
You can combine loops in various ways. For example, you can
have one loop inside of a loop or a loop inside a loop inside a
loop. There is no limit to the number of loops you can have
inside of other loops, although you want to limit this. When a
loop is inside another loop, the second loop is nested in the
first loop. In this situation, the loop with another loop inside it
is called an outer loop , and the nested loop is called an inner
loop . When you have a nested loop, the inner loop iterates
through its iterable once for each time around the outer loop:
1
2 # http://tinyurl.com/gqjxjtq
3
4
5
6 for
7 i
in
range
(
1
,
3
):
print
(i)
for
letter
in
[
"a"
,
"b"
,
"c"
]:
print
(letter)
>> 1
>> a
>> b
>> c
>> 2
>> a
>> b
>> c
The nested for-loop will iterate through the list [“a”,
“b”, “c”] however many times the outer loop runs—in this
case, twice. If you changed your outer loop to run three times,
the inner loop would iterate through its list three times as well.
You can use two for-loops to add each number in a list to
all the numbers in another list:
1
# http://tinyurl.com/z7duawp
2
3
4
5
6 list1
7 =
[
8 1
9 ,
2
10
,
11 3
12 ,
4
]
list2
=
[
5
,
6
,
7
,
8
]
added
=
[]
for
i
in
list1:
for
j
in
list2:
added.append(i
+
j)
print
(added)
for
i
in
range
(
1
,
6
):
print
(i)
>> y or n?y
1
2
3
4
5
y or n?y
1
2
3
4
5
y or n?n
>>>
This program will print the numbers 1–5 until the user enters
n.
Vocabulary
Loop : A piece of code that continually executes instructions
until a condition defined in the code is satisfied.
Iterating : Using a loop to access each item in an iterable.
For-loop : A loop used to iterate through an iterable, like a
string, list, tuple, or dictionary.
Index variable : A variable that holds an integer representing
an index in an iterable.
While-loop : A loop that executes code as long as an
expression evaluates to True .
Infinite loop : A loop that never ends.
Break-statement : A statement with the keyword break in it
used to terminate a loop.
Continue-statement : A statement with the keyword
continue used to stop the current iteration of a loop and
move on to the next iteration of it.
Outer loop : A loop with a nested loop inside it.
Inner loop : A loop nested in another loop.
Challenges
1. Print each item in the following list: [“The Walking
Dead”, “Entourage”, “The Sopranos”, “The
Vampire Diaries”] .
2. Print all the numbers from 25 to 50 .
3. Print each item in the list from the first challenge and their
indexes.
4. Write a program with an infinite loop (with the option to
type q to quit) and a list of numbers. Each time through the
loop ask the user to guess a number on the list and tell them
whether or not they guessed correctly.
5. Multiply all the numbers in the list [8, 19, 148, 4]
with all the numbers in the list [9, 1, 33, 83] , and
append each result to a third list.
Solutions: http://tinyurl.com/z2m2ll5 .
Chapter 8. Modules
“Perseverance and spirit have done wonders in all ages.”
~ George Washington
Imagine you wrote a program with 10,000 lines of code. If you
put all of the code in one file, it would be difficult to navigate.
Every time there was an error or exception, you would have to
scroll through 10,000 lines of code to find the one line causing
the problem. Programmers solve this issue by dividing large
programs into multiple pieces, called modules — another
name for a Python file with code in it—containing each piece.
Python allows you to use code from one module in another
module. Python also has built-in modules , modules that are
built into Python and contain important functionality. In this
chapter, you learn about modules and how to use them.
import
math
3
4
5
6 import
7 math
math.
pow
(
2
,
3
)
>> 8.0
First, import the math module at the top of your file. You
should import all of your modules at the top of your file to
make it easy to see which ones you are using in your program.
Next, call the pow function with math.pow(2, 3) . The
function returns 8.0 as the result.
The random module is another built-in module. You can use
a function from it called randint to generate a random
integer: you pass it two integers, and it returns a random
integer between them:
1
2 # http://tinyurl.com/hr3fppn
3
4
5
6 # The output might not be 52
7
8 # when you run it—it's random!
9
10
11
import
random
random.randint(
0
,
100
)
>> 52
You can use the built-in statistics module to calculate
the mean, median, and mode in an iterable of numbers:
1
# http://tinyurl.com/jrnznoy
2
3
4
5
6 import
7 statistics
8
9
# mean
10
11 nums
12 =
[
13
1
14 ,
15 5
,
16 33
,
12
,
46
,
33
,
2
]
statistics.mean(nums)
# median
statistics.median(nums)
# mode
statistics.mode(nums)
>> 18.857142857142858
>> 12
>> 33
Use the built-in keyword module to check if a string is a
Python keyword:
1
2 # http://tinyurl.com/zjphfho
3
4
5
6 import
7 keyword
8
keyword.iskeyword(
"for"
)
keyword.iskeyword(
"football"
)
>> True
>> False
3
4
5
def
print_hello():
print
(
"Hello"
)
1
2 # http://tinyurl.com/j4xv728
3
4
5
6 import
7 hello
hello.print_hello()
>> Hello
In this example, you used the import keyword to use code
from your first module in your second module.
When you import a module, all of the code in it executes.
Create a module named module1.py with the following
code:
1
2 # http://tinyurl.com/zgyddhp
3
4
5
# code in module1
print
(
"Hello!"
)
>> Hello!
The code from module1.py will run when you import it in
another module named module2.py :
1
2 # http://tinyurl.com/jamt9dy
3
4
5
# code in module2
import
hello
>> Hello!
This behavior can be inconvenient. For instance, you might
have test code in your module that you do not want to run
when you import it. You can solve this problem by putting all
of the code in your module within the statement if
__name__ == “__main__” . For example, you could
change the code in module1.py from the previous example
to the following:
1
# http://tinyurl.com/j2xdzc7
2
3
4
5
6 # code in module1
if
__name__
=
=
"__main__"
:
print
(
"Hello!"
)
>> Hello!
When you run this program, the output is still the same. But
when you import it from module2.py , the code from
module1.p no longer runs, and Hello! does not print:
1
2 # http://tinyurl.com/jjccxds
3
4
5
# code in module2
import
hello
Vocabulary
Module : Another name for a Python file with code in it.
Built-in module : Modules that come with Python that contain
important functionality.
Import : Writing code that lets Python know where to look for
a module you plan on using.
Challenges
1. Call a different function from the statistics module.
2. Create a module named cubed with a function that takes a
number as a parameter, and returns the number cubed. Import
and call the function from another module.
Solutions: http://tinyurl.com/hlnsdot .
Chapter 9. Files
“Self-education is, I firmly believe, the only kind of education
there is.”
~ Isaac Asimov
You can use Python to work with files. For example, you can
use Python to read data from a file and to write data to a file.
Reading data from a file means accessing the file’s data.
Writing data to a file means adding or changing data in the
file. In this chapter, you will learn the basics of working with
files.
Writing to Files
The first step to working with a file is to open it with Python’s
built-in open function. The open function takes two
parameters: a string representing the path to the file to open
and a string representing the mode to open the file in.
The path to a file, or file path , represents the location on your
computer where a file resides. For example,
/Users/bob/st.txt is the file path to a file called
st.txt . Each word separated by a slash is the name of a
folder. Together, it represents the location of a file. If a file
path only has the name of the file (with no folders separated
by slashes), Python will look for it in whatever folder you are
running your program from. You should not write a file path
yourself. Unix-like operating systems and Windows use a
different number of backslashes in their file paths. To avoid
problems with your program working across different
operating systems, you should always create file paths using
Python’s built-in os module . The path function in it takes
each folder in a file path as a parameter and builds the file path
for you:
1
# http://tinyurl.com/hkqfkar
2
3
4
5
6 import
7 os
os.path.join(
"Users"
,
"bob"
,
"st.txt"
)
>> ‘Users/bob/st.txt’
Creating file paths with the path function ensures they will
work on any operating system. Working with file paths can
still be tricky. Visit http://theselftaughtprogrammer.io/filepaths
if you are having trouble.
The mode you pass to the open function determines the
actions you will be able to perform on the file you open. Here
are a few of the modes you can open a file in:
“r” opens a file for reading only.
“w” opens a file for writing only. Overwrites the file if the file
exists. If the file does not exist, creates a new file for writing.
“w+” opens a file for reading and writing. Overwrites the
existing file if the file exists. If the file does not exist, creates a
new file for reading and writing.5
The open function returns an object, called a file object ,
which you can use to read and/or write to your file. When you
use the mode “w” , the open function creates a new file, if it
doesn’t already exist, in the directory your program is running
in.
You can then use the write method on the file object to write
to the file, and the close method to close it. If you open a
file using the open method, you must close it with the close
method. If you use the open method on multiple files and
forget to close them, it can cause problems in your program.
Here is an example of opening a file, writing to it, and closing
it:
1
2 # http://tinyurl.com/zfgczj5
3
4
5
6 st
=
open
(
"st.txt"
,
"w"
)
st.write(
"Hi from Python!"
)
st.close()
In this example, you use the open function to open the file
and save the file object it returns in the variable st . Then you
call the write method on st , which accepts a string as a
parameter and writes it to the new file Python created. Finally,
you close your file by calling the close method on the file
object.
f.write(
"Hi from Python!"
)
3
4
5
6 # make sure you've
7
8 # created the file from
9
# the previous example
10
with
open
(
"st.txt"
,
"r"
) as f:
print
(f.read())
3
4
5
6 my_list
7 =
list
8 ()
9
10
11
with
open
(
"st.txt"
,
"r"
) as f:
my_list.append(f.read())
print
(my_list)
CSV Files
Python comes with a built-in module that allows you to work
with CSV files . A CSV file has a .csv extension that
separates data using commas (CSV stands for Comma
Separated Values). Programs that manage spreadsheets like
Excel often use CSV files. Each piece of data separated by a
comma in a CSV file represents a cell in a spreadsheet, and
every line represents a row. A delimiter is a symbol, like a
comma or a vertical bar | , used to separate data in a CSV file.
Here are the contents of a CSV file named
self_taught.csv :
one,two,three
four,five,six
You could load this file into Excel, and one, two, and three
would each get cells in the first row of the spreadsheet, and
four, five, and six would each get cells in the second row.
You can use a with-statement to open a CSV file, but
inside the with-statement you need to use the csv
module to convert the file object into a csv object. The csv
module has a method called writer that accepts a file object
and a delimiter. The writer method returns a csv object
that has a method called writerow . The writerow
method accepts a list as a parameter, and you can use it to
write to a CSV file. Every item in the list gets written —
separated by the delimiter you pass to the writer method —
to a row in the CSV file. The writerow method only creates
one row, so you have to call it twice to create two rows:
1
2 # http://tinyurl.com/go9wepf
3
4
5
6 import
7 csv
8
9
10
with
11 open
12 (
"st.csv"
13
,
14 "w", newline=''
15 ) as f:
w
=
csv.writer(f,
delimiter
=
","
)
w.writerow([
"one"
,
"two"
,
"three"
])
w.writerow([
"four"
,
"five"
,
"six"
])
3
4
5
6 # make sure you've created
7
8 # the file from the previous
9
# example
10
11
12
13 import
14 csv
15
with
open
(
"st.csv"
,
"r"
) as f:
r
=
csv.reader(f, delimiter
=
","
)
for
row
in
r:
print
(
","
.join(row))
>> one,two,three
>> four,five,six
In this example, you open st.csv for reading and convert it
to a csv object using the reader method. You then iterate
through the csv object using a loop. Each time around the
loop, you call the join method on a comma to add a comma
between each piece of data in the file and print the contents the
way they appear in the original file (separated by commas).
Vocabulary
Reading : Accessing the file’s content.
Writing : Adding or changing data in the file.
File path : The location on your computer where a file resides.
With-statement : A compound statement with an action that
automatically occurs when Python leaves it.
File object : An object you can use to read or write to a file.
CSV file : A file with a .csv extension that separates data
using commas (CSV stands for Comma Separated Values).
Frequently used in programs that manage spreadsheets, like
Excel.
Delimiter : A symbol, like a comma, used to separate data in a
CSV file.
Challenges
1. Find a file on your computer and print its contents using
Python.
2. Write a program that asks a user a question, and saves their
answer to a file.
3. Take the items in this list of lists: [[“Top Gun”,
“Risky Business”, “Minority Report”],
[“Titanic”, “The Revenant”, “Inception”],
[“Training Day”, “Man on Fire”, “Flight”]]
and write them to a CSV file. The data from each list should
be a row in the file, with each item in the list separated by a
comma.
Solutions: http://tinyurl.com/hll6t3q .
Chapter 10.
Bringing It All Together
“All I have learned, I learned from books.”
~ Abraham Lincoln
In this chapter, you are going to combine the concepts you’ve
learned so far and build a text-based game, the classic
Hangman. If you’ve never played Hangman, here’s how it
works:
1. Player One picks a secret word and draws a line for each
letter in it (you will use an underscore to represent each line).
2. Player Two tries to guess the word one letter at a time.
3. If Player Two guesses a letter correctly, Player One replaces
the corresponding underscore with the correct letter. In this
version of the game, if a letter appears twice in a word, you
have to guess it twice.
OR
If Player Two guesses incorrectly, Player One draws a body
part of a hanged stick figure (starting with the head).
4. If Player Two completes the word before the drawing of the
hangman is complete, they win. If not, they lose.
Hangman
Here is the beginning of your Hangman code:
1
# http://tinyurl.com/jhrvs94
2
3
4
5
6 def
7 hangman(word):
8
9 wrong
10 =
0
11
12
13 stages
14 =
["",
15
16
17 "________ "
,
18
"| "
,
"| | "
,
"| 0 "
,
"| /|\ "
,
"| / \ "
,
"| "
rletters
=
list
(word)
board
=
[
"__"
]
*
len
(word)
win
=
False
print
(
"Welcome to Hangman"
)
if
char
in
rletters:
cind
=
rletters \
.index(char)
board[cind]
=
char
rletters[cind]
=
'$'
else
:
wrong
+
=
1
print
((
" "
.join(board)))
e
=
wrong
+
1
print
(
"\n"
.join(stages[
0
: e]))
if
"__"
not
in
board:
print
(
"You win!"
)
print
(
" "
.join(board))
win
=
True
break
3
4 if
5 not
win:
6
7
print
(
"\n"
.join(stages[
0
: \
wrong]))
print
(
"You lose! It was {}."
.
format
(word))
3
4
5
6 def
7 hangman(word):
8
9 wrong
10 =
0
11
12
13 stages
14 =
["",
15
16
17 "________ "
,
18
19
20 "| "
21 ,
22
23 "| | "
24 ,
25
26 "| 0 "
27 ,
28
29
"| /|\ "
30 ,
31
32
"| / \ "
33 ,
34
35
"| "
36
37
38 ]
39
40
rletters
41 =
42 list
(word)
43
44
45 board
46 =
[
47 "__"
]
*
len
(word)
win
=
False
print
(
"Welcome to Hangman"
)
while
wrong <
len
(stages)
-
1
:
print
(
"\n"
)
msg
=
"Guess a letter"
char
=
input
(msg)
if
char
in
rletters:
cind
=
rletters \
.index(char)
board[cind]
=
char
rletters[cind]
=
'$'
else
:
wrong
+
=
1
print
((
" "
.join(board)))
e
=
wrong
+
1
print
(
"\n"
.join(stages[
0
: e]))
if
"__"
not
in
board:
print
(
"You win!"
)
print
(
" "
.join(board))
win
=
True
break
if
not
win:
print
(
"\n"
.join(stages[
0
: \
wrong]))
print
(
"You lose! It was {}."
.
format
(word))
hangman(
"cat"
)
Challenge
1. Modify the game, so a word is selected randomly from a list
of words.
Solution: http://tinyurl.com/j7rb8or .
Chapter 11.
Practice
“Practice doesn’t make perfect. Practice makes myelin, and
myelin makes perfect.”
~Daniel Coyle
If this is your first programming book, I recommend spending
time practicing before moving on to the next section. The
following is some resources to explore and advice on what to
do if you are stuck.
Read
1.
http://programmers.stackexchange.com/questions/44177/what-
is-the-single-most-effective-thing-you-did-to-improve-your-
programming-skil
Other Resources
I’ve compiled a list of programming resources at
http://www.theselftaughtprogrammer.io/resources .
Getting Help
If you get stuck, I have a few suggestions. First, post your
question in the Self-Taught Programmers Facebook group
located at
https://www.facebook.com/groups/selftaughtprogrammers .
The group is a community of friendly programmers (and
aspiring ones) that can help answer any questions you have.
I also recommend checking out http://www.stackoverflow.com
, a website where you can post programming questions and get
answers from members of the community.
I created an online course based on this book available at
goselftaught.com you might find helpful as well.” as a new
paragraph after “get answers from members of the
community.”
Learning to rely on other people’s help was an important
lesson for me. Struggling to figure things out is a major part of
the learning process; but at some point, it becomes
counterproductive. In the past, when I worked on projects, I
used to struggle beyond the point of productivity. If that
happens today, I post a question online, if I can’t find the
answer there already. Every time I’ve posted a question online,
someone has answered it. To that end, I can’t say enough
about how helpful and friendly the programming community
is.
Chapter 12.
Programming Paradigms
“There are only two kinds of languages: the ones people
complain about and the ones nobody uses.”
~Bjarne Stroustrup
A programming paradigm is a style of programming. There
are many different programming paradigms. To program
professionally, you need to learn either the object-oriented or
functional programming paradigms. In this chapter, you will
learn about procedural programming, functional programming,
and object-oriented programming—with a focus on object-
oriented programming.
State
One of the fundamental differences between the various
programming paradigms is the handling of state . State is the
value of a program’s variables while it is running. Global
state is the value of a program’s global variables while it is
running.
Procedural Programming
In Part I, you programmed using the procedural
programming paradigm: a programming style in which you
write a sequence of steps moving toward a solution—with
each step changing the program’s state. In procedural
programming, you write code to “do this, then that”:
1
# http://tinyurl.com/jv2rrl8
2
3
4
5
6 x
7 =
2
8
y
=
4
z
=
8
xyz
=
x
+
y
+
z
xyz
>> 14
Each line of code in this example changes the program’s state.
First, you define x , then y , then z . Finally, you define the
value of xyz .
When you program procedurally, you store data in global
variables and manipulate it with functions:
1
2 # http://tinyurl.com/gldykam
3
4
5
6 rock
7 =
[]
8
9 country
10 =
[]
11
12
13
14
def
15 collect_songs():
16
17
song
18 =
19 "Enter a song."
20
21
ask
22 =
23 "Type r or c. q to quit"
24
25
26
27 while
28 True
29 :
30
31 genre
32 =
input
33 (ask)
34
35
if
genre
=
=
"q"
:
break
if
genre
=
=
"r"
:
rk
=
input
(song)
rock.append(rk)
elif
genre
=
=
(
"c"
):
cy
=
input
(song)
country.append(cy)
else
:
print
(
"Invalid."
)
print
(rock)
print
(country)
collect_songs()
Functional Programming
Functional programming originates from the lambda
calculus: the smallest universal programming language in the
world (created by the mathematician Alonzo Church).
Functional programming addresses the problems that arise in
procedural programming by eliminating global state. A
functional programmer relies on functions that do not use or
change global state, the only state they use are the parameters
you pass to the function. The result a function returns is
usually passed on to another function. A functional
programmer can thus avoid global state by passing it from
function to function. Eliminating global state removes side
effects and the problems that come with them.
There is a lot of jargon in functional programming, and Mary
Rose Cook cuts through it with her definition, “Functional
code is characterized by one thing: the absence of side effects.
It doesn’t rely on data outside the current function, and it
doesn’t change data that exists outside the current function.”6
She follows her definition with an example of a function that
has side effects:
1
2 # http://tinyurl.com/gu9jpco
3
4
5
6 a
7 =
0
8
9
def
increment():
global
a
a
+
=
1
3
4
5
def
increment(a):
return
a
+
1
Object-Oriented Programming
The object-oriented programming paradigm also addresses
the problems that arise in procedural programming by
eliminating global state, but instead of storing state in
functions, it is stored in objects. In object-oriented
programming, classes define a set of objects that can interact
with each other. Classes are a mechanism for the programmer
to classify and group together similar objects. Think of a bag
of oranges. Each orange is an object. All oranges have the
same attributes, such as color and weight, but the values of
these attributes vary from one orange to the next. You can use
a class to model oranges and create orange objects with
different values. For instance, you can define a class that
allows you to create an orange object that is dark orange and
weighs 10 oz, and an orange object that is light orange and
weighs 12 oz.
Every object is an instance of a class. If you define a class
called Orange , and create two Orange objects, each one is
an instance of the class Orange ; they have the same data
type—Orange . You can use the terms object and instance
interchangeably. When you define a class, all of the instances
of that class will be similar: They all have the attributes
defined in the class they are an instance of, such as color or
weight for a class representing an orange—but each instance
can have different values for these attributes.
In Python, a class is a compound statement with a header and
suites. You define a class with the syntax class [name]:
[suites] where [name] is the name of the class and
[suites] are the class’ suites you define. By convention,
classes in Python always start with a capital letter, and you
write them in camelCase—which means if a class name has
more than one word, the first letters of all the words should be
capitalized LikeThis , instead of separated by an underscore
(the convention for function names). A suite in a class can be a
simple statement or a compound statement called a method .
Methods are like functions, but you define them inside of a
class, and you can only call them on the object the class
creates (like you did in Part I when you called methods like
“hello”.upper() on strings). Method names, like
function names, should be all lowercase with words separated
by underscores.
You define methods with the same syntax as functions, with
two differences: you must define a method as a suite in a class,
and it has to accept at least one parameter (except in special
cases). By convention, you always name the first parameter of
a method self . You have to define at least one parameter
when you create a method, because when you call a method on
an object, Python automatically passes the object that called
the method to the method as a parameter:
1
2 # http://tinyurl.com/zrmjape
3
4
5
6 class
Orange:
def
__init__(
self
):
print
(
"Created!"
)
def
__init__(
self
, w, c):
self
.weight
=
w
self
.color
=
c
print
(
"Created!"
)
self
.weight
=
w
self
.color
=
c
print
(
"Created!"
)
or1
=
Orange(
10
,
"dark orange"
)
print
(or1)
>> Created!
>> <__main__.Orange object at
0x101a787b8>
After the class definition, you instantiate the Orange class
with the code Orange(10, “dark orange”) and
Created! prints. Then, you print the Orange object itself,
and Python tells you it is an Orange object and gives you its
location in memory (the location in memory printed on your
computer will not be the same as this example).
Once you’ve created an object, you can get the value of its
instance variables with the syntax [object_name].
[variable_name] :
1
2 # http://tinyurl.com/grwzeo4
3
4
5
6 class
7 Orange:
8
9 def
10 __init__(
self
11
, w, c):
12
13
self
.weight
=
w
self
.color
=
c
print
(
"Created!"
)
or1
=
Orange(
10
,
"dark orange"
)
print
(or1.weight)
print
(or1.color)
>> Created!
>> 10
>> dark orange
You can change the value of an instance variable with the
syntax [object_name].[variable_name] =
[new_value] :
1
2 # http://tinyurl.com/jsxgw44
3
4
5
6 class
7 Orange:
8
9 def
10 __init__(
self
11
, w, c):
12
13
14 self
.weight
15 =
16 w
17
self
.color
=
c
print
(
"Created!"
)
or1
=
Orange(
10
,
"dark orange"
)
or1.weight
=
100
or1.color
=
"light orange"
print
(or1.weight)
print
(or1.color)
>> Created!
>> 100
>> light orange
Although the instance variables color and weight started
with the values “dark orange” and 10 , you were able to
change their values to “light orange” and 100 .
You can use the Orange class to create multiple oranges:
1
2 # http://tinyurl.com/jrmxlmo
3
4
5
6 class
7 Orange:
8
9 def
10 __init__(
self
11
, w, c):
12
13
self
.weight
=
w
self
.color
=
c
print
(
"Created!"
)
or1
=
Orange(
4
,
"light orange"
)
or2
=
Orange(
8
,
"dark orange"
)
or3
=
Orange(
14
,
"yellow"
)
>> Created!
>> Created!
>> Created!
There is more to an orange than its physical properties, like
color and weight. Oranges also do things, like rot, that you
can model with methods. Here is how you can give an
Orange object the ability to rot:
1
# http://tinyurl.com/zcp32pz
2
3
4
5
6 class
7 Orange():
8
9 def
10 __init__(
self
11
, w, c):
12
13
14 """weights are in oz"""
15
16 self
17 .weight
=
18 w
19
20
self
.color
=
c
self
.mold
=
0
print
(
"Created!"
)
def
rot(
self
, days, temp):
self
.mold
=
days
*
temp
orange
=
Orange(
6
,
"orange"
)
print
(orange.mold)
orange.rot(
10
,
98
)
print
(orange.mold)
>> Created!
>> 0
>> 98.0
The method rot accepts two parameters: the numbers of days
since someone picked the orange, and the average temp during
that time. When you call it, the method uses a formula to
increment the instance variable mold , which works because
you can change the value of any instance variable inside of
any method. Now, the orange can rot.
You can define multiple methods in a class. Here is an
example of modeling a rectangle with a method to calculate its
area, and another method to change its size:
1
2 # http://tinyurl.com/j28qoox
3
4
5
6 class
7 Rectangle():
8
9 def
10 __init__(
self
11
, w, l):
12
13
14 self
.width
15 =
16 w
17
18 self
19 .
20 len
=
21 l
22
def
area(
self
):
return
self
.width
*
self
.
len
def
change_size(
self
, w, l):
self
.width
=
w
self
.
len
=
l
rectangle
=
Rectangle(
10
,
20
)
print
(rectangle.area())
rectangle.change_size(
20
,
40
)
print
(rectangle.area())
>> 200
>> 800
In this example, Rectangle objects have two instance
variables: len and width . The area method returns the
area of the Rectangle object by multiplying the instance
variables together, and the change_size method changes
them by assigning them to the numbers the caller passes in as
parameters.
Object-oriented programming has several advantages. It
encourages code reuse, and thus decreases the amount of time
spent developing and maintaining code. It also encourages
breaking problems up into multiple pieces, which results in
code that is easy to maintain. A disadvantage of object-
oriented programming is that creating programs takes extra
effort because a great deal of planning is often involved in
designing them.
Vocabulary
Programming paradigm : A style of programming.
State : The value of a program’s variables while it is running.
Global state : The value of a program’s global variables while
it is running.
Procedural programming : A programming style in which
you write a sequence of steps moving toward a solution—with
each step changing the program’s state.
Functional programming : Functional programming
addresses the problems that arise in procedural programming
by eliminating global state by passing it from function to
function.
Side effect : Changing the state of a global variable.
Object-oriented : A programming paradigm where you define
objects that interact with each other.
Classes : A mechanism allowing the programmer to classify
and group together similar objects.
Methods : Methods are suites in a class. They are like
functions, but you define them inside of a class, and you can
only call them on the object the class creates.
Instance : Every object is an instance of a class. Every
instance of a class has the same type as all the other instances
of that class.
Instance variables : Variables that belong to an object.
Magic method : A method Python uses in different situations,
like initializing an object.
Instantiating a class : Creating a new object using a class.
Challenges
1. Define a class called Apple with four instance variables
that represent four attributes of an apple.
2. Create a Circle class with a method called area that
calculates and returns its area. Then create a Circle object,
call area on it, and print the result. Use Python’s pi function
in the built-in math module.
3. Create a Triangle class with a method called area that
calculates and returns its area. Then create a Triangle
object, call area on it, and print the result.
4. Make a Hexagon class with a method called
calculate_perimeter that calculates and returns its
perimeter. Then create a Hexagon object, call
calculate_perimeter on it, and print the result.
Solutions: http://tinyurl.com/gpqe62e .
Chapter 13.
The Four Pillars of Object-Oriented
Programming
“Good design adds value faster than it adds cost.”
~Thomas C. Gale
There are four main concepts in object-oriented programming:
encapsulation, abstraction, polymorphism, and inheritance.
Together, they form the four pillars of object-oriented
programming . All four concepts must be present in a
programming language for it to be considered a fully object-
oriented programming language, like Python, Java, and Ruby.
In this chapter, you will learn about each of the four pillars of
object-oriented programming.
Encapsulation
Encapsulation refers to two concepts. The first is that in
object-oriented programming, objects group variables (state)
and methods (for altering state or doing calculations that use
state) in a single unit—the object:
1
# http://tinyurl.com/j74o5rh
2
3
4
5
6 class
7 Rectangle():
8
9 def
10 __init__(
self
11
, w, l):
12
self
.width
=
w
self
.
len
=
l
def
area(
self
):
return
self
.width
*
self
.
len
In this case, the instance variables len and width hold the
object’s state. The object’s state is grouped in the same unit
(the object) as the method area . The method uses the
object’s state to return the rectangle’s area.
The second concept, encapsulation, refers to hiding a class’s
internal data to prevent the client , the code outside the class
that uses the object, from directly accessing it:
1
2 # http://tinyurl.com/jtz28ha
3
4
5
6 class
7 Data:
8
9 def
10 __init__(
self
):
self
.nums
=
[
1
,
2
,
3
,
4
,
5
]
def
change_data(
self
, index, n):
self
.nums[index]
=
n
3
4
5
6 class
7 Data:
8
9 def
10 __init__(
self
11
):
12
13
14 self
.nums
15 =
16 [
1
17 ,
18 2
,
19
3
20 ,
4
,
5
]
def
change_data(
self
, index, n):
self
.nums[index]
=
n
data_one
=
Data()
data_one.nums[
0
]
=
100
print
(data_one.nums)
data_two
=
Data()
data_two.change_data(
0
,
100
)
print
(data_two.nums)
>> [100, 2, 3, 4, 5]
>> [100, 2, 3, 4, 5]
Both ways of changing an item in the nums instance variable
work, but what happens if you decide to make the variable
nums a tuple instead of a list? If you make this change, any
client code trying to alter the items in the variable nums , like
you did with nums[0] = 100 , will no longer work,
because tuples are immutable.
Many programming languages solve this problem by allowing
programmers to define private variables and private
methods : variables and methods that objects can access in the
code that implements the various methods, but the client
cannot. Private variables and methods are useful when you
have a method or variable that your class uses internally, but
you plan to change the implementation of your code later (or
you want to preserve the flexibility of that option), and thus
don’t want whoever is using the class to rely on them because
they might change (and would then break the client’s code).
Private variables are an example of the second concept
encapsulation refers to; private variables hide a class’s internal
data to prevent the client from directly accessing it. Public
variables , on the other hand, are variables a client can access.
Python does not have private variables. All of Python’s
variables are public. Python solves the problem private
variables address another way—by using naming conventions.
In Python, if you have a variable or method the caller should
not access, you precede its name with an underscore. Python
programmers know if the name of a method or variable starts
with an underscore, they shouldn’t use it (although they are
still able to at their own risk):
1
2 # http://tinyurl.com/jkaorle
3
4
5
6 class
7 PublicPrivateExample:
8
9 def
10 __init__(
self
11
):
12
13
14 self
.public
15 =
16 "safe"
17
self
._unsafe
=
"unsafe"
def
public_method(
self
):
# clients can use this
pass
def
_unsafe_method(
self
):
pass
Abstraction
Abstraction is the process of “taking away or removing
characteristics from something in order to reduce it to a set of
essential characteristics.”7 You use abstraction in object-
oriented programming when you model objects using classes
and omit unnecessary details.
Say you are modeling a person. A person is complex: they
have a hair color, eye color, height, weight, ethnicity, gender,
and more. If you create a class to represent a person, some of
these details may not be relevant to the problem you are trying
to solve. An example of abstraction is creating a Person
class, but omitting some attributes a person has, like an eye
color and height. The Person objects your class creates are
abstractions of people. It is a representation of a person
stripped down to only the essential characteristics necessary
for the problem you are solving.
Polymorphism
Polymorphism is “the ability (in programming) to present the
same interface for differing underlying forms (data types).”8
An interface is a function or a method. Here is an example of
presenting the same interface for different data types:
1
2 # http://tinyurl.com/hrxd7gn
3
4
5
6 print
(
"Hello, World!"
)
print
(
200
)
print
(
200.1
)
type
(
200
)
type
(
200.1
)
a_shape.draw_triangle()
if
type
(a_shape)
=
=
"Square"
:
a_shape.draw_square()
if
type
(a_shape)
=
=
"Circle"
:
a_shape.draw_circle()
# Drawing shapes
# with polymorphism
shapes
=
[tr1,
sw1,
cr1]
for
a_shape
in
shapes:
a_shape.draw()
Inheritance
Inheritance in programming is similar to genetic inheritance.
In genetic inheritance, you inherit attributes like eye color
from your parents. Similarly, when you create a class, it can
inherit methods and variables from another class. The class
that is inherited from is the parent class , and the class that
inherits is the child class . In this section, you will model
shapes using inheritance. Here is a class that models a shape:
1
2 # http://tinyurl.com/zrnqeo3
3
4
5
6 class
7 Shape():
8
9 def
10 __init__(
self
11
, w, l):
12
13
14 self
.width
15 =
16 w
17
self
.
len
=
l
def
print_size(
self
):
print
(
"""{} by {}
"""
.
format
(
self
.width,
self
.
len
))
my_shape
=
Shape(
20
,
25
)
my_shape.print_size()
>> 20 by 25
With this class, you can create Shape objects with width
and len . In addition, Shape objects have the method
print_size , which prints their width and len .
You can define a child class that inherits from a parent class by
passing the name of the parent class as a parameter to the child
class when you create it. The following example creates a
Square class that inherits from the Shape class:
1
2 # http://tinyurl.com/j8lj35s
3
4
5
6 class
7 Shape():
8
9 def
10 __init__(
self
11
, w, l):
12
13
14 self
.width
15 =
16 w
17
18
self
19 .
len
20
=
21 l
def
print_size(
self
):
print
(
"""{} by {}
"""
.
format
(
self
.width,
self
.
len
))
class
Square(Shape):
pass
a_square
=
Square(
20
,
20
)
a_square.print_size()
>> 20 by 20
Because you passed the Shape class to the Square class as a
parameter; the Square class inherits the Shape class’s
variables and methods. The only suite you defined in the
Square class was the keyword pass , which tells Python not
to do anything.
Because of inheritance, you can create a Square object, pass
it a width and length, and call the method print_size on it
without writing any code (aside from pass ) in the Square
class. This reduction in code is important because avoiding
repeating code makes your program smaller and more
manageable.
A child class is like any other class; you can define methods
and variables in it without affecting the parent class:
1
# http://tinyurl.com/hwjdcy9
2
3
4
5
6 class
7 Shape():
8
9 def
10 __init__(
self
11
, w, l):
12
13
14 self
.width
15 =
16 w
17
18 self
19 .
20 len
=
21 l
22
def
print_size(
self
):
print
(
"""{} by {}
"""
.
format
(
self
.width,
self
.
len
))
class
Square(Shape):
def
area(
self
):
return
self
.width
*
self
.
len
a_square
=
Square(
20
,
20
)
print
(a_square.area())
>> 400
When a child class inherits a method from a parent class, you
can override it by defining a new method with the same name
as the inherited method. A child class’s ability to change the
implementation of a method inherited from its parent class is
called method overriding .
1
2 # http://tinyurl.com/hy9m8ht
3
4
5
6 class
7 Shape():
8
9 def
10 __init__(
self
11
, w, l):
12
13
14 self
.width
15 =
16 w
17
18
self
19 .
len
20
=
21 l
22
23
24
25
def
26 print_size(
27
28 self
):
print
(
"""{} by {}
"""
.
format
(
self
.width,
self
.
len
))
class
Square(Shape):
def
area(
self
):
return
self
.width
*
self
.
len
def
print_size(
self
):
print
(
"""I am {} by {}
"""
.
format
(
self
.width,
self
.
len
))
a_square
=
Square(
20
,
20
)
a_square.print_size()
>> I am 20 by 20
In this case, because you defined a method named
print_size , the newly defined method overrides the
parent method of the same name, and it prints a new message
when you call it.
Composition
Now that you’ve learned about the four pillars of object-
oriented programming, I am going to cover one more
important concept: composition . Composition models the
“has a” relationship by storing an object as a variable in
another object. For example, you can use composition to
represent the relationship between a dog and its owner (a dog
has an owner). To model this, first you define classes to
represent dogs and people:
1
2 # http://tinyurl.com/zqg488n
3
4
5
6 class
7 Dog():
8
9 def
10 __init__(
self
11
,
12
13
14 name,
15
16 breed,
owner):
self
.name
=
name
self
.breed
=
breed
self
.owner
=
owner
class
Person():
def
__init__(
self
, name):
self
.name
=
name
3
4 # Continue from
5
6 # last example
7
8
9
mick
10 =
Person(
"Mick Jagger"
)
stan
=
Dog(
"Stanley"
,
"Bulldog"
,
mick)
print
(stan.owner.name)
Vocabulary
The four pillars of object-oriented programming : The four
main concepts in object-oriented programming: inheritance,
polymorphism, abstraction, and encapsulation.
Inheritance : In genetic inheritance, you inherit attributes like
eye color from your parents. Similarly, when you create a
class, it can inherit methods and variables from another class.
Parent class : The class that is inherited from.
Child class : The class that inherits.
Method overriding : A child class’s ability to change the
implementation of a method inherited from its parent class.
Polymorphism : Polymorphism is “the ability (in
programming) to present the same interface for differing
underlying forms (data types).”9
Abstraction : The process of “taking away or removing
characteristics from something in order to reduce it to a set of
essential characteristics.”10
Client : The code outside the class that uses the object.
Encapsulation : Encapsulation refers to two concepts. The
first concept is that in object-oriented programming, objects
group variables (state) and methods (for altering state) in a
single unit—the object. The second concept is hiding a class’s
internal data to prevent the client, the person using the code,
from accessing it.
Composition : Composition models the “has a” relationship
by storing an object as a variable in another object.
Challenges
1. Create Rectangle and Square classes with a method
called calculate_perimeter that calculates the
perimeter of the shapes they represent. Create Rectangle
and Square objects and call the method on both of them.
2. Define a method in your Square class called
change_size that allows you to pass in a number that
increases or decreases (if the number is negative) each side of
a Square object by that number.
3. Create a class called Shape . Define a method in it called
what_am_i that prints “I am a shape” when called.
Change your Square and Rectangle classes from the
previous challenges to inherit from Shape , create Square
and Rectangle objects, and call the new method on both of
them.
4. Create a class called Horse and a class called Rider . Use
composition to model a horse that has a rider.
Solutions: http://tinyurl.com/hz9qdh3 .
Chapter 14.
More Object-Oriented Programming
“Treat your code like poetry and take it to the edge of the bare
minimum.”
~Ilya Dorman
In this chapter, I cover additional concepts related to object-
oriented programming.
1
# http://tinyurl.com/h7ypzmd
2
3
4
5
6 class
7 Square:
8
pass
print
(Square)
3
4
5
6 class
7 Rectangle():
8
9 def
10 __init__(
self
11
, w, l):
12
13
14 self
.width
15 =
16 w
17
self
.
len
=
l
def
print_size(
self
):
print
(
"""{} by {}
"""
.
format
(
self
.width,
self
.
len
))
my_rectangle
=
Rectangle(
10
,
24
)
my_rectangle.print_size()
>> 10 by 24
In this example, width and len are instance variables.
Class variables belong to the object Python creates for each
class definition and the objects they create. You define class
variables like regular variables (but you must define them
inside of a class). You can access them with class objects, and
with an object created with a class object. You access them the
same way you access instance variables (preceding the
variable name with self .). Class variables are useful; they
allow you to share data between all of the instances of a class
without relying on global variables:
1
2 # http://tinyurl.com/gu9unfc
3
4
5
6 class
7 Rectangle():
8
9 recs
10 =
[]
11
12
13
14
15 def
16 __init__(
self
17 , w, l):
18
19
self
20 .width
21 =
22 w
23
24 self
25 .
len
26 =
l
self
.recs.append((
self
.width,
self
.
len
))
def
print_size(
self
):
print
(
"""{} by {}
"""
.
format
(
self
.width,
self
.
len
))
r1
=
Rectangle(
10
,
24
)
r2
=
Rectangle(
20
,
40
)
r3
=
Rectangle(
100
,
200
)
print
(Rectangle.recs)
>> [(10, 24), (20, 40), (100, 200)]
In this example, you added a class variable called recs to the
Rectangle class. You defined it outside of the __init__
method because Python only calls the __init__ method
when you create an object, and you want to be able to access
the class variable using the class object (which does not call
the __init__ method).
Next, you created three Rectangle objects. Each time a
Rectangle object is created, the code in the __init__
method appends a tuple containing the width and length of the
newly created object to the recs list. With this code,
whenever you create a new Rectangle object, it is
automatically added to the recs list. By using a class
variable, you were able to share data between the different
objects created by a class, without having to use a global
variable.
Magic Methods
Every class in Python inherits from a parent class called
Object . Python utilizes the methods inherited from
Object in different situations—like when you print an
object:
1
2 # http://tinyurl.com/ze8yr7s
3
4
5
6 class
7 Lion:
8
9 def
10 __init__(
self
, name):
self
.name
=
name
lion
=
Lion(
"Dilbert"
)
print
(lion)
3
4
5
6 class
7 Lion:
8
9 def
10 __init__(
self
11
, name):
12
13
14 self
.name
=
name
def
__repr__(
self
):
return
self
.name
lion
=
Lion(
"Dilbert"
)
print
(lion)
>> Dilbert
Because you overrode the __repr__ method inherited from
Object and changed it to return the Lion object’s name,
when you print a Lion object, its name— in this case,
Dilbert — prints instead of something like
<__main__.Lion object at 0x101178828> that
the __repr__ method would have returned.
Operands in an expression must have a magic method the
operator can use to evaluate the expression. For example, in
the expression 2 + 2 , each integer object has a magic
method called __add__ that Python calls when it evaluates
the expression. If you define an __add__ method in a class,
you can use the objects it creates as operands in an expression
with the addition operator:
1
# http://tinyurl.com/hlmhrwv
2
3
4
5
6 class
7 AlwaysPositive:
8
9 def
10 __init__(
self
11
, number):
12
13
14 self
.n
15 =
16 number
17
18
def
__add__(
self
, other):
return
abs
(
self
.n
+
other.n)
x
=
AlwaysPositive(
-
20
)
y
=
AlwaysPositive(
10
)
print
(x
+
y)
>> 10
AlwaysPositive objects can be used as operands in an
expression with the addition operator because you defined the
__add__ method. When Python evaluates an expression with
an addition operator, it calls the method __add__ on the first
operand object, passes the second operand object into
__add__ as a parameter, and returns the result.
In this case, __add__ uses the built-in function abs to return
the absolute value of two numbers added together in an
expression. Because you defined __add__ this way, two
AlwaysPositive objects evaluated in an expression with
the addition operator will always return the absolute value of
the sum of the two objects; thus, the result of the expression is
always positive.
Is
The keyword is returns True if two objects are the same
object, and False if not:
1
2 # http://tinyurl.com/gt28gww
3
4
5
6 class
7 Person:
8
9 def
10 __init__(
self
11
):
12
13
14 self
.name
15 =
'Bob'
bob
=
Person()
same_bob
=
bob
print
(bob
is
same_bob)
another_bob
=
Person()
print
(bob
is
another_bob)
>> True
>> False
When you use the keyword is in an expression with the
objects bob and same_bob as operators, the expression
evaluates to True because both variables point to the same
Person object. When you create a new Person object and
compare it to the original bob , the expression evaluates to
False because the variables point to different Person
objects.
Use the is keyword to check if a variable is None :
1
2 # http://tinyurl.com/jjettn2
3
4
5
6 x
7 =
10
8
9 if
10 x
is
11
None
12 :
13
14
print
15 (
"x is None :( "
)
else
:
print
(
"x is not None"
)
x
=
None
if
x
is
None
:
print
(
"x is None"
)
else
:
print
(
"x is None :( "
)
Vocabulary
Class variable : A class variable belongs to a class object and
the objects it creates.
Instance variable : An instance variable belongs to an object.
Private variables : A variable an object can access, but the
client cannot.
Private method : A method an object can access, but the
client cannot.
Public variable : A variable a client can access.
Challenges
1. Add a square_list class variable to a class called
Square so that every time you create a new Square object,
the new object gets added to the list.
2. Change the Square class so that when you print a
Square object, a message prints telling you the len of each of
the four sides of the shape. For example, if you create a square
with Square(29) and print it, Python should print 29 by
29 by 29 by 29 .
3. Write a function that takes two objects as parameters and
returns True if they are the same object, and False if not.
Solutions: http://tinyurl.com/j9qjnep .
Chapter 15.
Bringing It All Together
“It’s all talk until the code runs.”
~Ward Cunningham
In this chapter, you are going to create the popular card game
War. In War, each player draws a card from the deck, and the
player with the highest card wins. You will build War by
defining classes representing a card, a deck, a player, and
finally, the game itself.
Cards
Here is a class that models playing cards:
1
# http://tinyurl.com/jj22qv4
2
3
4
5
6 class
7 Card:
8
9 suits
10 =
[
11
"spades"
12 ,
13
14
"hearts"
15 ,
16
17
"diamonds"
18 ,
19
20
"clubs"
21
]
22
23
24
25
26 values
=
27 [
28 None
29 ,
None
30 ,
31 "2"
,
32 "3"
33 ,
34
35
"4"
36 ,
37 "5"
,
38 "6"
39 ,
"7"
40 ,
41
42
"8"
43
,
44 "9"
45 ,
"10"
46 ,
47
48
"Jack"
49
,
50 "Queen"
,
"King"
,
"Ace"
]
def
__init__(
self
, v, s):
self
.value
=
v
self
.suit
=
s
def
__lt__(
self
, c2):
if
self
.value < c2.value:
return
True
if
self
.value
=
=
c2.value:
if
self
.suit < c2.suit:
return
True
else
:
return
False
return
False
def
__gt__(
self
, c2):
if
self
.value > c2.value:
return
True
if
self
.value
=
=
c2.value:
if
self
.suit > c2.suit:
return
True
else
:
return
False
return
False
def
__repr__(
self
):
v
=
self
.values[
self
.value]
+
\
" of "
+
\
self
.suits[
self
.suit]
return
v
The Card class has two class variables, suits and values
. suits is a list of strings representing all the suits a card
could be: spades , hearts , diamonds , clubs .
values is a list of strings representing the different numeric
values a card could be: 2–10 , Jack , Queen , King and
Ace . The items at the first two indexes of the values list are
None , so that the strings in the list match up with the index
they represent—so the string “2” in the values list is at
index 2 .
Card objects have two instance variables: suit and value
—each represented by an integer. Together, the instance
variables represent what kind of card the Card object is. For
example, you create a 2 of hearts by creating a Card
object and passing it the parameters 2 (for the suit) and 1 (for
the value—1 because hearts is at index 1 in the suits list).
The definitions in the magic methods __lt__ and __gt__
allow you to compare two Card objects in an expression
using the greater than and less than operators. The code in
these methods determines if the card is greater than or less
than the other card passed in as a parameter. The code in these
magic methods can also handle if the cards have the same
value—for example if both cards are 10s. If this occurs, the
methods use the value of the suits to break the tie. The suits
are arranged in order of strength in the suits list—with the
strongest suit last, and thus assigned the highest index, and the
least powerful suit assigned the lowest index.
1
2 # http://tinyurl.com/j6donnr
3
4
5
6 card1
=
Card(
10
,
2
)
card2
=
Card(
11
,
3
)
print
(card1 < card2)
>> True
1
2 # http://tinyurl.com/hc9ktlr
3
4
5
6 card1
=
Card(
10
,
2
)
card2
=
Card(
11
,
3
)
print
(card1 > card2)
>> False
The last method in the Card class is the magic method
__repr__ . Its code uses the value and suit instance
variables to look up the value and suit of the card in the
values and suits lists, and returns them so you can print
the card a Card object represents:
1
2 # http://tinyurl.com/z57hc75
3
4
5
card
=
Card(
3
,
2
)
print
(card)
>> 3 of diamonds
Deck
Next, you need to define a class to represent a deck of cards:
1
2 # http://tinyurl.com/jz8zfz7
3
4 from
5 random
import
6 shuffle
7
8
9
10 class
Deck:
11
12
13 def
14 __init__(
self
15 ):
16
17
self
18 .cards
19 =
[]
for
i
in
range
(
2
,
15
):
for
j
in
range
(
4
):
self
.cards\
.append(Card(i,
j))
shuffle(
self
.cards)
def
rm_card(
self
):
if
len
(
self
.cards)
=
=
0
:
return
return
self
.cards.pop()
for
card
in
deck.cards:
print
(card)
>> 4 of spades
>> 8 of hearts
…
Player
You need a class to represent each player in the game to keep
track of their cards and how many rounds they’ve won:
1
# http://tinyurl.com/gwyrt2s
2
3
4
5
6 class
7 Player:
8
def
__init__(
self
, name):
self
.wins
=
0
self
.card
=
None
self
.name
=
name
Game
Finally, you need a class to represent the game:
1
2 # http://tinyurl.com/huwq8mw
3
4
5
6 class
7 Game:
8
9 def
10 __init__(
self
11
):
12
13
14 name1
=
15 input
16 (
"p1 name "
17
)
18
19
20 name2
=
21 input
22 (
"p2 name "
23 )
24
25
self
26
.deck
27
28 =
Deck()
29
30
31 self
32 .p1
=
33 Player(name1)
34
35
self
36
.p2
37 =
38 Player(name2)
39
40
41
42 def
43 wins(
self
44
, winner):
45
46
47 w
=
48 "{} wins this round"
49
50
w
51 =
52 w.
format
53
(winner)
54
55
56
print
57 (w)
58
59
60
61
def
62 draw(
63 self
, p1n, p1c, p2n, p2c):
64
d
=
"{} drew {} {} drew {}"
d
=
d.
format
(p1n,
p1c,
p2n,
p2c)
print
(d)
def
play_game(
self
):
cards
=
self
.deck.cards
print
(
"beginning War!"
)
while
len
(cards) >
=
2
:
m
=
"q to quit. Any "
+
\
"key to play:"
response
=
input
(m)
if
response
=
=
'q'
:
break
p1c
=
self
.deck.rm_card()
p2c
=
self
.deck.rm_card()
p1n
=
self
.p1.name
p2n
=
self
.p2.name
self
.draw(p1n,
p1c,
p2n,
p2c)
if
p1c > p2c:
self
.p1.wins
+
=
1
self
.wins(
self
.p1.name)
else
:
self
.p2.wins
+
=
1
self
.wins(
self
.p2.name)
win
=
self
.winner(
self
.p1,
self
.p2)
print
(
"War is over.{} wins"
.
format
(win))
def
winner(
self
, p1, p2):
if
p1.wins > p2.wins:
return
p1.name
if
p1.wins < p2.wins:
return
p2.name
return
"It was a tie!"
3
4
5
6 from
7 random
import
8 shuffle
9
10
11
12 class
Card:
13
14
15 suits
16 =
[
17 "spades"
18 ,
19
20 "hearts"
21 ,
22
23
"diamonds"
24 ,
25
26
"clubs"
27 ]
28
29
values
30 =
31 [
None
32 ,
33 None
,
34
"2"
35 ,
36 "3"
,
37
38
39 "4"
,
40 "5"
41 ,
42 "6"
,
43 "7"
44 ,
45
46 "8"
47 ,
"9"
48
,
49 "10"
50 ,
51
52 "Jack"
53 ,
"Queen"
54 ,
55
56
"King"
57 ,
58 "Ace"
]
59
60
61
62
63 def
__init__(
64
self
65 , v, s):
66
67
"""suit + value are ints"""
68
69
70 self
.value
71
=
72 v
73
74
self
75 .suit
76 =
s
77
78
79
80
81 def
__lt__(
82 self
83 , c2):
84
85 if
86 self
.value < c2.value:
87
88
89 return
True
90
91
92 if
93 self
.value
94 =
95 =
c2.value:
96
97
98 if
99 self
.suit < c2.suit:
100
101
102 return
True
103
104
105 else
:
106
107
108
109 return
110 False
111
112 return
113 False
114
115
116
117 def
118 __gt__(
self
119
, c2):
120
121
122 if
self
123 .value > c2.value:
124
125
return
126 True
127
128
if
129
self
130 .value
131 =
=
132 c2.value:
133
134
if
135
136 self
137 .suit > c2.suit:
138
139 return
140 True
141
142 else
:
return
False
return
False
def
__repr__(
self
):
v
=
self
.values[
self
.value]
+
\
" of "
+
\
self
.suits[
self
.suit]
return
v
class
Deck:
def
__init__(
self
):
self
.cards
=
[]
for
i
in
range
(
2
,
15
):
for
j
in
range
(
4
):
self
.cards\
.append(Card(i,
j))
shuffle(
self
.cards)
def
rm_card(
self
):
if
len
(
self
.cards)
=
=
0
:
return
return
self
.cards.pop()
class
Player:
def
__init__(
self
, name):
self
.wins
=
0
self
.card
=
None
self
.name
=
name
class
Game:
def
__init__(
self
):
name1
=
input
(
"p1 name "
)
name2
=
input
(
"p2 name "
)
self
.deck
=
Deck()
self
.p1
=
Player(name1)
self
.p2
=
Player(name2)
def
wins(
self
, winner):
w
=
"{} wins this round"
w
=
w.
format
(winner)
print
(w)
def
draw(
self
, p1n, p1c, p2n, p2c):
d
=
"{} drew {} {} drew {}"
d
=
d.
format
(p1n,
p1c,
p2n,
p2c)
print
(d)
def
play_game(
self
):
cards
=
self
.deck.cards
print
(
"beginning War!"
)
while
len
(cards) >
=
2
:
m
=
"q to quit. Any "
+
\
"key to play:"
response
=
input
(m)
if
response
=
=
'q'
:
break
p1c
=
self
.deck.rm_card()
p2c
=
self
.deck.rm_card()
p1n
=
self
.p1.name
p2n
=
self
.p2.name
self
.draw(p1n,
p1c,
p2n,
p2c)
if
p1c > p2c:
self
.p1.wins
+
=
1
self
.wins(
self
.p1.name)
else
:
self
.p2.wins
+
=
1
self
.wins(
self
.p2.name)
win
=
self
.winner(
self
.p1,
self
.p2)
print
(
"War is over.{} wins"
.
format
(win))
def
winner(
self
, p1, p2):
if
p1.wins > p2.wins:
return
p1.name
if
p1.wins < p2.wins:
return
p2.name
return
"It was a tie!"
game
=
Game()
game.play_game()
Finding Bash
You can find Bash on your computer by searching for
Terminal from the icon titled Search your computer
and online resources if you are using Ubuntu, or
from Spotlight search if you are using a Mac.
Commands
Bash is similar to the Python Shell. You type commands,
which are like functions in Python, into Bash. Then you type a
space and the parameters you want to pass to the command (if
any). Hit the enter key, and Bash returns the result. The
command echo is similar to the print function in Python.
Whenever you see a dollar sign followed by a command, in
either this book or in programming documentation, it means
you need to type the command into the command-line:
# http://tinyurl.com/junx62n
$ python3
print("Hello, World!")
Recent Commands
You can scroll through your recent commands by pressing the
up and down arrows in Bash. To see a list of all of your recent
commands use the command history :
# http://tinyurl.com/go2spbt
$ history
$ pwd
>> /Users/coryalthoff
Your operating system represents its directories, and your
directory location, with a tree. In computer science, a tree is an
important concept called a data structure (covered in Part IV).
In a tree, there is a root at the top. The root can have branches,
and each one of the branches can have more branches, and
those branches can have branches, ad infinitum. The following
image is an example of a tree that represents the directories in
an operating system:
Navigating
You can change directories by passing the command cd an
absolute or relative path as a parameter. Enter the cd
command followed by the absolute path / to navigate to your
operating system’s root directory:
# http://tinyurl.com/hjgz79h
$ cd /
$ pwd
>> /
The list directory command, ls , prints the directories and
folders in your current working directory:
# http://tinyurl.com/gw4d5yw
$ ls
$ cd ~
$ mkdir tstp
$ ls
>> tstp
Now, use the cd command to enter the tstp directory by
passing it the relative path to tstp as a parameter:
# http://tinyurl.com/zp3nb2l
$ cd tstp
$ cd ..
$ rmdir tstp
Finally, verify that you deleted the directory with the ls
command.
# http://tinyurl.com/z32xn2n
$ ls
Flags
Commands have a concept called flags that allow the issuer of
the command to change the command’s behavior. Flags are
options for commands that can have a value of either True or
False . By default, all of a command’s flags start set to
False . If you add a flag to a command, Bash sets the value
of the flag to True and the behavior of the command changes.
To set a flag to True , you put one (- ) or two (— ) hyphen
symbols in front of the name of the flag (depending on the
operating system).
For example, you can add the flag —author to the ls
command to set the author flag to True . Adding this flag
to the ls command alters its behavior. When you add this flag
to the ls command, it prints all of the directories and files in a
directory, but also prints the name of the author, the person
that created them.
On Unix, you use one hyphen in front of a flag:
# http://tinyurl.com/j4y5kz4
$ ls -author
$ ls --author
>> drwx––+ 13 coryalthoff 442B Sep 16
17:25 Pictures
>> drwx––+ 25 coryalthoff 850B Nov 23
18:09 Documents
Hidden Files
Your operating system and many programs on your computer
store data in hidden files. Hidden files are files that, by default,
are not shown to users because changing them could affect the
programs that depend on them. Hidden files start with a
period, for example, .hidden . You can view hidden files by
adding the flag -a , which stands for all, to the ls command.
The command touch creates a new file from the command
line.
The touch command creates a new file. Use it to create a
hidden file named .self_taught :
# http://tinyurl.com/hfawo8t
$ touch .self_taught
Pipes
In Unix-like operating systems, the vertical bar character (| )
is called a pipe . You can use a pipe to pass the output of a
command to another command as its input. For example, you
can use the output of the ls command as the input of the
less command (make sure you are not in an empty
directory):
# http://tinyurl.com/zjne9f5
$ ls | less
>> Applications …
The result is a text file with the output of ls opened up in the
program less (press q to quit less).
Environmental Variables
Environmental variables are variables, stored in your
operating system, that programs can use to get data about the
environment they are running in such as the name of the
computer the program is running on or the name of the
operating system user running the program. You can create a
new environmental variable in Bash with the syntax export
variable_name=[variable_value] . To reference an
environmental variable in Bash, you must put a dollar sign in
front of its name:
# http://tinyurl.com/jjbc9v2
$ export x=100
$ echo $x
>> 100
An environmental variable created like this only exists in the
Bash window you created it in. If you exit the Bash window
you created the environmental variable in, reopen it and type
echo $x , Bash will no longer print 100 because the
environmental variable x no longer exists.
You can persist an environmental variable by adding it to a
hidden file used by Unix-like operating systems, located in
your home directory, called .profile . Use your GUI to
navigate to your home directory. You can find the file path to
your home directory from the command line with pwd ~. Use
a text editor to create a file called .profile . Type export
x=100 into the first line of the file, and save the file. Close
and reopen Bash, and you should be able to print the
environmental variable x :
# http://tinyurl.com/j5wjwdf
$ echo $x
>> 100
The variable will persist as long as it’s in your .profile
file. You can delete the variable by removing it from your
.profile file.
Users
Operating systems can have multiple users. A user is a person
that uses the operating system. Each user is assigned a
username and password, which enables them to log in and use
the operating system. Each user also has a set of permissions:
operations they are allowed to perform. You can print the
name of your operating system user with the command
whoami (the examples in this section will not work on Bash
on Windows or the Bash web app) :
1
$ whoami
>> coryalthoff
Normally, you are the user you created when you installed
your operating system. But this user is not the most powerful
user in your operating system. The highest-level user, who is
the user with the highest set of permissions, is called the root
user. Every system has a root user who can, for example,
create and delete other users.
For security reasons, you usually do not log in as the root user.
Instead, you precede commands that you need to issue as the
root user with the command sudo (superuser do). sudo
allows you to issue commands as the root user without
compromising your system’s security by actually logging in as
the root user. Here is an example of using the echo command
with sudo :
$ sudo echo Hello, World!
Vocabulary
Command-line interface : A command-line interface is a
program you type instructions into that your operating system
executes.
Command-line : Another name for a command-line interface.
Bash : A program that comes with most Unix-like operating
systems that you type instructions into and your operating
system executes.
Command prompt : A command-line interface that comes
with Windows.
Directory : Another word for a folder on your computer.
Working directory : The directory you are currently in.
Path: A way of expressing the location in your operating
system of a file or directory.
Absolute path : The location of a file or directory starting
from the root directory.
Relative path : The location of a file or directory starting from
your current working directory.
Pipe : The character | . On Unix-like operating systems, you
can use a pipe to pass the output of a command to another
command as its input.
Environmental variables : Variables that your operating
system and other programs store data in.
$PATH : When you type a command into the Bash command
shell, it looks for the command in all the directories stored in
an environmental variable named $PATH .
User : A person that uses the operating system.
Permissions : Operations operating system users are allowed
to do.
Root user : The highest-level user, the user with the highest
set of permissions.
Challenges
1. Print Self-taught in Bash.
2. Navigate to your home directory from another directory
using an absolute and relative path.
3. Create an environmental variable called
$python_projects that is an absolute path to the
directory where you keep your Python files. Save the variable
in your .profile file and then use the command cd
$python_projects to navigate there.
Solutions: http://tinyurl.com/zdeyg8y .
Chapter 17.
Regular Expressions
“Talk is cheap. Show me the code.”
~Linus Torvalds
Many programming languages and operating systems support
regular expressions : a “sequence of characters that define a
search pattern.”11 Regular expressions are helpful because you
can use them to search a file or other data for a complex
pattern. For example, you can use a regular expression to
match all of the numbers in a file. In this chapter, you will
learn to define and pass regular expressions to grep , a
command on Unix-like operating systems that searches a file
for patterns and returns the text it finds in the file that matches
the pattern. You will also learn to use regular expressions to
search strings for patterns in Python.
Setup
To get started, create a file called zen.txt . From the
command-line (make sure you are inside the directory where
you created zen.txt ) enter the command python3 -c
“import this” . This will print The Zen of Python ,
a poem by Tim Peters:
The Zen of Python
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!
The -c flag tells Python you are going to pass it a string
containing Python code. Python then executes the code. When
Python executes import this , it prints The Zen of
Python (a message hidden in code like this poem is called an
Easter egg ). Enter the function exit() into Bash to quit
Python, then copy and paste The Zen of Python into the
file zen.txt .
By default, on Ubuntu, the grep command prints matched
words in red in its output, but on Unix it does not. If you are
using a Mac, you can change this by setting the following
environmental variables in Bash:
# http://tinyurl.com/z9prphe
$ export GREP_OPTIONS='--color=always'
$ export GREP_OPTIONS='--color=always'
A Simple Match
The grep command accepts two parameters: a regular
expression and the filepath of the file to search for the pattern
defined in the regular expression. The simplest kind of pattern
to match with a regular expression is a simple match, a string
of words that matches the same string of words. To see an
example of a simple match, enter the following command in
the directory where you created the file zen.txt :
# http://tinyurl.com/jgh3x4c
>> Beautiful
You can use regular expressions in Python with its built-in
library, re (regular expressions). The re module comes with a
method called findall . You pass in a regular expression as
a parameter, then a string and it returns a list with all the items
in the string that the pattern matches:
1
2 # http://tinyurl.com/z9q2286
3
4
5
6 import
7 re
8
9
10
l
11 =
12 "Beautiful is better than ugly."
13
matches
=
re.findall(
"Beautiful"
, l)
print
(matches)
>> [‘Beautiful’]
In this example, the findall method found a match and
returned a list with the match (Beautiful ) as the first item.
You can ignore case in the findall method by passing in
re.IGNORECASE to the findall method as the third
parameter:
1
2 # http://tinyurl.com/jzeonne
3
4
5
6 import
7 re
8
9
10
l
11 =
12 "Beautiful is better than ugly."
13
14
15
matches
=
re.findall(
"beautiful"
,
l,
re.IGNORECASE)
print
(matches)
>> [‘Beautiful’]
3
4
5
6 import
7 re
8
9
10
zen
11 =
12 """Although never is
13
often better than
14
15
*right* now.
16
17 If the implementation
18
19 is hard to explain,
20
it's a bad idea.
21
22 If the implementation
23
24 is easy to explain,
25
it may be a good
26
idea. Namespaces
are one honking
do more of those!
"""
m
=
re.findall(
"^If"
,
zen,
re.MULTILINE)
print
(m)
3
4
5
6 import
7 re
8
9
10
string
11 =
12 "Two too."
13
m
=
re.findall(
"t[ow]o"
,
string,
re.IGNORECASE)
print
(m)
line,
re.IGNORECASE)
print
(m)
Repetition
The asterisk symbol (* ) adds repetition to your regular
expressions. With an asterisk, “the preceding item will be
matched zero or more times.”12 For instance, you can use an
asterisk to match tw followed by any amount of o s:
# http://tinyurl.com/j8vbwq8
>> two
>> twoo
In a regular expression, a period matches any character. If you
follow a period with an asterisk, it instructs the regular
expression to match any character zero or more times. You can
use a period followed by an asterisk to match everything
between two characters:
# http://tinyurl.com/h5x6cal
>> __hello__
The regular expression __.*__ matches any character
between and including the two double underscores. An
asterisk is greedy , which means that it will try to match as
much text as it can. For example, if you add more words with
double underscores, the regular expression from the previous
example will match everything from the first underscore to the
last underscore:
# http://tinyurl.com/j9v9t24
>> __hi__bye__hi__
You do not always want to match patterns greedily. You can
follow an asterisk with a question mark to make the regular
expression non-greedy . A non-greedy regular expression
looks for the least number of matches possible. In this case, it
would stop matching on the first double underscore it comes
across, instead of matching everything between the very first
underscore and the very last underscore. Grep does not have
non-greedy matching, but in Python, you can use a question
mark for non-greedy matching:
1
2 # http://tinyurl.com/j399sq9
3
4
5
6 import
7 re
8
9
10
t
11 =
12 "__one__ __two__ __three__"
13
14
found
=
re.findall(
"__.*?__"
, t)
for
match
in
found:
print
(match)
>> __one__
>> __two__
>> __three__
You can use non-greedy matching in Python to create the
game Mad Libs (if you don’t remember Mad Libs, it is a game
with a paragraph of text with various words missing that the
players are prompted to fill in):
1
2 # http://tinyurl.com/ze6oyua
3
4
5 import
6 re
7
8
9
10
11
text
12 =
13 """Giraffes have aroused
14
15
the curiosity of __PLURAL_NOUN__
16
17
18 since earliest times. The
19
20 giraffe is the tallest of all
21
22
living __PLURAL_NOUN__, but
23
24
25 scientists are unable to
26
27
28 explain how it got its long
29
30
__PART_OF_THE_BODY__. The
31
32
33 giraffe's tremendous height,
34
35 which might reach __NUMBER__
36
37
__PLURAL_NOUN__, comes from
38
39
40 it legs and __BODYPART__.
41
42 """
43
44
45
def
46 mad_libs(mls):
47
48
"""
49
50
51 :param mls: String
by double underscores.
Underscores cannot
__hint_hint__ only
__hint__.
"""
hints
=
re.findall(
"__.*?__"
,
mls)
if
hints
is
not
None
:
for
word
in
hints:
q
=
"Enter a {}"
\
.
format
(word)
new
=
input
(q)
mls
=
mls.replace(word,
new,
1
)
print
(
'\n'
)
mls
=
mls.replace(
"\n"
, "")
print
(mls)
else
:
print
(
"invalid mls"
)
mad_libs(text)
>> enter a __PLURAL_NOUN__
In this example, you use the re.findall method to get a
list of all of the words in the variable text surrounded by
double underscores (each one is a hint for the type of word the
user needs to replace). Then, you loop through the list and use
each hint to ask the person using the program to supply a new
word. You then create a new string, replacing the hint with the
user-supplied word. Once the loop finishes, you print the new
string with all of the words you collected from the user.
Escaping
You can escape characters (ignore a character’s meaning and
match it instead) in regular expressions like you did earlier
with strings in Python, by prefixing a character in a regular
expression with a backslash \ :
# http://tinyurl.com/zkbumfj
>> I love $
Normally, the dollar sign means a match is only valid if it
occurs at the end of the line, however, because you escaped it,
your regular expression matches the dollar sign character
instead.
And in Python:
1
2 # http://tinyurl.com/zy7pr4l
3
4
5
6 import
7 re
8
9
10
line
11 =
12 "I love $"
13
14
15
m
=
re.findall(
"\\$"
,
line,
re.IGNORECASE)
print
(m)
>> [‘$’]
Vocabulary
Regular Expressions : A “sequence of characters that define a
search pattern.”13
Easter egg : A message hidden in code.
Greedy : A regular expression that is greedy will try to match
text as it can.
Non-greedy : A non-greedy regular expression looks for the
least number of matches possible.
Challenges
1. Write a regular expression that matches the word Dutch in
The Zen of Python .
2. Come up with a regular expression that matches all the
digits in the string Arizona 479, 501, 870.
California 209, 213, 650 .
3. Create a regular expression that matches any word that
starts with any character and is followed by two o’s. Then use
Python’s re module to match boo and loo in the sentence
The ghost that says boo haunts the loo.
Solutions: http://tinyurl.com/jmlkvxm .
Chapter 18.
Package Managers
“Every programmer is an author.”
~Sercan Leylek
A package manager is a program that installs and manages
other programs. They are useful because you often need to use
other programs to create new software. For example, web
developers often use a web framework : a program that helps
you build a website. Programmers use package managers to
install web frameworks, as well as a variety of other programs.
In this chapter, you will learn to use the package manager pip .
Packages
A package is software “packaged” for distribution—it
includes the files that make up the actual program, as well as
metadata : data about data like the software’s name, version
number, and dependencies : the programs a program relies on
to run properly. You can use a package manager to download a
package and install it as a program on your computer. The
package manager handles downloading any dependencies the
package has.
Pip
In this section, I will show you how to use pip, a package
manager for Python, to download Python packages. Once
you’ve downloaded a package with pip, you can import it as a
module in a Python program. First, check to see if pip is
installed on your computer by opening Bash, or the Command
Prompt if you are using Windows, and entering the command
pip :
# http://tinyurl.com/hmookdf
$ pip
>> Password:
>> Successfully installed flask-0.11.1
On Windows, you need to use the command-line as an
administrator. Right-click on the command-prompt icon and
select Run as administrator .
Inside the Command Prompt enter:
# http://tinyurl.com/hyxm3vt
3
4
5
6 from
7 flask
import
8 Flask
9
10
11
12 app
=
13
Flask(__name__)
14
15
@app
.route(
'/'
)
def
index():
return
"Hello, World!"
app.run(port
=
'8000'
)
pip freeze
>> Flask==0.11.11
…
Finally, you can uninstall a program with pip uninstall
[package_name] . Uninstall Flask with the following
command:
# http://tinyurl.com/ht8mleo
Virtual Environments
Eventually, you will want to install your Python packages into
a virtual environment instead of installing all of your
packages into site-packages . Virtual environments allow
you to keep the Python packages for your different
programming projects separate. You can learn more about
virtual environments at http://docs.python-
guide.org/en/latest/dev/virtualenvs .
Vocabulary
Package manager : A program that installs and manages
other programs.
Web framework : A program that helps you build a website.
Package : Software “packaged” for distribution.
Metadata : Data about data.
Dependencies : The programs a program relies on to run
properly.
Apt-get : A package manager that comes with Ubuntu.
Pip : A package manager for Python.
$PYTHONPATH : Python looks for modules in a list of
folders stored in an environmental variable called
$PYTHONPATH .
Site-packages : A folder in $PYTHONPATH . This folder is
where pip installs packages.
PyPI : A website that hosts Python packages.
Virtual environment : You use a virtual environment to keep
the Python packages for your different programming projects
separate.
Challenge
1. Find a package on PyPI (https://pypi.python.org ) and
download it with pip.
Solution: http://tinyurl.com/h96qbw2.
Chapter 19.
Version Control
“I object to doing things that computers can do.”
~ Olin Shivers
Writing software is a team sport. When you are working on a
project with another person (or an entire team), you all need to
be able to make changes to the codebase —the folders and
files that make up your software, and you need to keep those
changes in sync. You could periodically email each other with
your changes and combine multiple different versions
yourself, but that would be tedious.
Also, what would happen if you both made changes to the
same part of the project? How do you decide whose changes to
use? These are the kinds of problems a version control
system solves. A version control system is a program designed
to help you easily collaborate on projects with other
programmers.
Git and SVN are two popular version control systems.
Typically, you use a version control system in conjunction
with a service that stores your software in the cloud. In this
chapter, you will use Git to put software on GitHub , a
website that stores your code on the cloud.
Repositories
A repository is a data structure created by a version control
system, like Git, that keeps track of all the changes in your
programming project. A data structure is a way of organizing
and storing information: lists and dictionaries are examples of
data structures (you will learn more about data structures in
Part IV). When you see a repository, it will look like a
directory with files in it. You will use Git to interact with the
data structure that keeps track of the project’s changes.
When you are working on a project managed by Git, there will
be multiple repositories (usually one for each person working
on the project). Typically, everybody working on the project
has a repository on their computer called a local repository ,
which keeps track of all the changes they make to the project.
There is also a central repository , hosted on a website like
GitHub, that all the local repositories communicate with to
stay in sync with each other (each repository is completely
separate). A programmer working on the project can update
the central repository with the changes they’ve made in their
local repository, and they can update their local repository
with the newest changes other programmers have made to the
central repository. If you are working on a project with one
other programmer, your setup will look like this:
Getting Started
If GitHub changes the layout of their website, the instructions
in this section will change. If that happens, I will provide new
instructions at http://theselftaughtprogrammer.io/git . To get
started, you need to create a GitHub account at
https://github.com/join . To create a new repository on GitHub,
login to your GitHub account (once you have created it) and
click on the + button at the top right corner of the screen. Click
New repository from the drop-down menu. Give the
repository the name hangman . Select the Public option,
and check the box Initialize the repository
with a README . Now, click Create repository .
On GitHub, hit the button in the top right corner and select
Your profile .
You will see the name of your repository: hangman . Click on
it. This part of the website is your central repository. You will
see a button that says Clone Or Download . When you
click on it, you will see a link. Save this link.
Before you can precede, you need to install Git. You can find
installation instructions at https://www.git-
scm.com/book/en/v2/Getting-Started-Installing-Git .
Once you have installed Git, you can use it from the
command-line. Type git into the command-line:
# http://tinyurl.com/gs9d5hf
$ git
$ ls
>> hangman
$ cd hangman
$ git remote -v
$ git status
hangman.py
You should see the file hangman.py in red. You can stage a
file with the command git add [file] :
# http://tinyurl.com/hncnyz9
$ git status
hangman.py
Stage it again:
# http://tinyurl.com/gowe7hp
Pulling Example
In this section, you are going to update your local repository
by pulling the changes from your central repository. You will
need to do this whenever you want to update your local
repository with the changes another programmer made to the
central repository.
Go to your central repository and press the button Create
new file . Create a file called new.py and then press the
button Commit new file . This file is not yet in your local
repository, so your local repository is out of sync with your
central repository. You can update your local repository with
changes from your central repository with the command git
pull origin master :
# http://tinyurl.com/gqf2xue
Reverting Versions
Git saves your project every time you commit a file. With Git,
you can revert to any previous commit—you can “rewind”
your project. For example, you can return your project back to
a commit you made last week. All of your files and folders
will be the same as they were last week. Then you can
immediately jump forward to a more recent commit. Each
commit has a commit number : a unique sequence of
characters that Git uses to identify a commit.
You can view your project’s history of commits with the
command git log , which prints all of your commits:
# http://tinyurl.com/h2m7ahs
$ git log
>> commit
8e032f54d383e5b7fc640a3686067ca14fa8b43f
Author: Cory Althoff
<coryedwardalthoff@gmail.com> Date: Thu
Dec 8 16:20:03 2016 -0800
Create new.py
commit
b0dab51849965144d78de21002464dc0f9297fdc
Author: Cory Althoff <coryalthoff@Corys-
MacBook-Pro.local> Date: Thu Dec 8
16:12:10 2016 -0800
my first commit
commit
f5d44dab1418191f6c2bbfd4a2b2fcf74ef5a68f
Author: Cory Althoff
<coryedwardalthoff@gmail.com> Date: Thu
Dec 8 15:53:25 2016 -0800 Initial commit
You should see three commits. Your first commit was when
you created the central repository. Your second commit was
when you updated the central repository with your
hangman.py file. Your third commit was when you created
the file new.py . Each commit has a commit number. You
can switch your project to another commit by passing a
commit number to the command git checkout . In this
example, I could revert my project to what it looked like when
I first created it with the command git checkout
f5d44dab1418191f6c2bbfd4a2b2fcf74ef5a68f .
diff
The command git diff shows you the difference between
a file in your local repository versus your central repository.
Create a new file called hello_world.py in your local
repository, and add the code print(“Hello, World!”)
to it.
Now stage the file:
# http://tinyurl.com/h6msygd
$ git status
Next Steps
In this chapter, I covered the features of Git you will use most
frequently. Once you’ve mastered the basics, I recommend
you spend time learning about Git’s more advanced features
like branching and merging at
http://theselftaughtprogrammer.io/git .
Vocabulary
Codebase : The folders and files that make up your software.
Version control system : A program designed to let you easily
collaborate on projects with other programmers.
Git : A popular version control system.
SVN : A popular version control system.
GitHub : A website that stores your code on the cloud.
Repository : A data structure created by a version control
system, like Git, that keeps track of the changes in your
programming project.
Data structure : A way of organizing and storing information.
Lists and dictionaries are examples of data structures.
Local repository : The repository on your computer.
Central repository : A repository hosted on a website like
GitHub that all of the local repositories communicate with to
stay in sync with each other.
Pushing : Updating your central repository with changes from
your local repository.
Pulling : Updating your local repository with changes from
your central repository.
Staging : Telling Git which files (with modifications) you
want to push to your central repository.
Committing : Giving a command that tells Git to record the
changes you made in your repository.
Commit : A version of your project that Git saves.
Commit number : A unique sequence of characters Git uses
to identify a commit.
Challenges
1. Create a new repository on GitHub. Put all your Python files
from the exercises you’ve completed so far into one directory
on your computer and push them to your new repository.
Chapter 20.
Bringing It All Together
“The magic of myth and legend has come true in our time.
One types the correct incantation on a keyboard, and a display
screen comes to life, showing things that never were nor could
be…”
~ Frederick Brooks
In this chapter, you will see how powerful programming is by
building a web scraper : a program that extracts data from a
website. Once you can build a web scraper, you have the
ability to collect data from the largest collection of information
in existence. The power of web scrapers, and how easy they
are to build, is one of the reasons I got hooked on
programming, and I hope it has the same effect on you.
HTML
Before you build a web scraper, you need a quick primer on
HTML : hypertext markup language. HTML is one of the
fundamental technologies programmers build websites with,
along with CSS and JavaScript. HTML is a language that
gives a website structure. HTML is made up of tags a web
browser uses to layout web pages. You can build an entire
website with HTML. It won’t be interactive or look very good,
because JavaScript is what makes websites interactive, and
CSS is what gives them style, but it will be a website. Here is
a website that displays the text Hello, World!
# http://tinyurl.com/jptzkvp
<html lang="en">
<head>
<meta charset="UTF-8">
<title>My Website</title>
</head>
<body>
Hello, World!
<a href="https://www.google.com"/>
click here</a>
</body>
</html>
Save this HTML into a file. Open the file with your web
browser by clicking on the file (you may have to right-click
and change the default program to open the file with a web
browser like Chrome). Once you’ve opened the file with your
web browser, you will see a website that says Hello
World! with a link to Google.
3
4
5
6 import
7 urllib.request
8
from
9 bs4
10 import
BeautifulSoup
11
12
13
14
class
15 Scraper:
def
__init__(
self
,
site):
self
.site
=
site
def
scrape(
self
):
pass
3
4
5
6 def
7 scrape(
self
):
r
=
urllib.request\
.urlopen(
self
.site)
html
=
r.read()
3
4
5
6 def
7 scrape(
self
8 ):
9
10
r
=
urllib.request\
.urlopen(
self
.site)
html
=
r.read()
parser
=
"html.parser"
sp
=
BeautifulSoup(html,
parser)
3
4
5
6 def
7 scrape(
self
8 ):
9
10
r
11
=
12 urllib.request\
13
14
.urlopen(
15 self
16 .site)
html
=
r.read()
parser
=
"html.parser"
sp
=
BeautifulSoup(html,
parser)
for
tag
in
sp.find_all(
"a"
):
url
=
tag.get(
"href"
)
if
url
is
None
:
continue
if
"html"
in
url:
print
(
"\n"
+
url)
r
=
urllib.request\
.urlopen(
self
.site)
html
=
r.read()
parser
=
"html.parser"
sp
=
BeautifulSoup(html,
parser)
for
tag
in
sp.find_all(
"a"
):
url
=
tag.get(
"href"
)
if
url
is
None
:
continue
if
"html"
in
url:
print
(
"\n"
+
url)
news
=
"https://news.google.com/
"
Scraper(news).scrape()
When you run your program, the output should look similar to
this:
https://www.washingtonpost.com/world/national-security/in-
foreign-bribery-cases-leniency-offered-to-companies-that-
turn-over-employees/2016/04/05/d7a24d94-fb43-11e5-9140-
e61d062438bb_story.html
http://www.appeal-democrat.com/news/unit-apartment-
complex-proposed-in-marysville/article_bd6ea9f2-fac3-11e5-
bfaf-4fbe11089e5a.html
http://www.appeal-democrat.com/news/injuries-from-yuba-
city-bar-violence-hospitalize-groom-to-be/article_03e46648-
f54b-11e5-96b3-5bf32bfbf2b5.html
Now that you can collect Google News’ headlines, the
possibilities are limitless. You could write a program to
analyze the most used words in the headlines. You could build
a program to analyze the sentiment of the headlines, and see if
it has any correlation with the stock market. With web
scraping, all the information in the world is yours for the
taking, and I hope that excites you as much as it does me.
Vocabulary
Web scraper : A program that extracts data from a website.
HTML : A language that gives a website structure.
HTML Tag : Like a programming keyword—it tells your
browser to do something.
Pars e: Parsing means taking a format like HTML and using a
programming language to give it structure. For example,
turning the data into an object.
Challenge
1. Modify your scraper to save the headlines in a file.
Data Structures
A data structure is a format used to store and organize
information. Data structures are fundamental to programming,
and most programming languages come with them built-in.
You already know how to use several of Python’s built-in data
structures, such as lists, tuples, and dictionaries. In this
chapter, you will learn how to create two more data structures:
stacks and queues.
Stacks
A stack is a data structure. Like a list, you can add and remove
items from a stack, except unlike a list, you can only add and
remove the last item. If you have the list [1, 2, 3] , you
can remove any of the items in it. If you have a stack that is
the same, you can only remove the last item in it, 3 . If you
remove the 3 , your stack looks like [1, 2] . Now you can
remove the 2 . Once you’ve removed the 2 , you can remove
the 1 , and the stack is empty. Removing an item from a stack
is called popping . If you put 1 back on the stack, it looks like
[1] . If you put a two onto the stack, it looks like [1, 2].
Putting an item onto a stack is called pushing . This kind of
data structure, where the last item put in is the first item taken
out, is called a last-in-first-out data structure (LIFO ).
You can think of a LIFO like a stack of dishes. If you stack
five dishes on top of each other, you would have to remove all
the other dishes to get to the one on the bottom of the stack.
Think of every piece of data in a stack like a dish, to access it
you have to pull out the data at the top.
In this section, you are going to build a stack. Python has a
library with both of the data structures I cover in this chapter,
but building your own will show you how they work. The
stack will have five methods: is_empty , push , pop , and
size . The method is_empty returns True if your stack is
empty and False otherwise. push adds an item to the top of
your stack. pop removes and returns the top item from your
stack. peek returns the top item in the stack, but does not
remove it. size returns an integer representing the number of
items in your stack. Here is a stack implemented in Python:
1
2 # http://tinyurl.com/zk24ps6
3
4
5
6 class
7 Stack:
8
9 def
10 __init__(
self
11
):
12
13
14 self
.items
15 =
16 []
17
18
19
20 def
21 is_empty(
self
22
):
23
24
25 return
self
26 .items
27 =
=
[]
def
push(
self
, item):
self
.items.append(item)
def
pop(
self
):
return
self
.items.pop()
def
peek(
self
):
last
=
len
(
self
.items)
-
1
return
self
.items[last]
def
size(
self
):
return
len
(
self
.items)
3
4
5
stack
=
Stack()
print
(stack.is_empty())
>> True
When you add a new item to the stack, is_empty returns
False :
1
2 # http://tinyurl.com/zsexcal
3
4
5
6 stack
=
Stack()
stack.push(
1
)
print
(stack.is_empty())
>> False
Call the pop method to remove an item from the stack, and
is_empty once again returns True :
1
2 # http://tinyurl.com/j72kswr
3
4
5
6 stack
7 =
Stack()
8
stack.push(
1
)
item
=
stack.pop()
print
(item)
print
(stack.is_empty())
>> 1
>> True
Finally, you can take a peek at a stack’s contents and get its
size:
1
2 # http://tinyurl.com/zle7sno
3
4
5
6 stack
7 =
Stack()
8
9
10
11 for
12 i
in
range
(
0
,
6
):
stack.push(i)
print
(stack.peek())
print
(stack.size())
>> 5
>> 6
3
4
5
6 class
7 Stack:
8
9 def
10 __init__(
self
11
):
12
13
14 self
.items
15 =
16 []
17
18
19
20
def
21 is_empty(
22 self
):
23
24
25 return
self
26 .items
27 =
28 =
29 []
30
31
32
33 def
34 push(
self
35 , item):
36
37
self
38
.items.append(item)
39
40
41
42
def
pop(
self
):
return
self
.items.pop()
def
peek(
self
):
last
=
len
(
self
.items)
-
1
return
self
.items[last]
def
size(
self
):
return
len
(
self
.items)
stack
=
Stack()
for
c
in
"Hello"
:
stack.push(c)
reverse
=
""
for
i
in
range
(
len
(stack.items)):
reverse
+
=
stack.pop()
print
(reverse)
>> olleH
First, you went through each character in the string “Hello”
, and put it in a stack. Then you iterated through the stack. You
took each item off the stack and into the variable reverse .
Once the iteration is complete, the original word is in reverse,
and your program prints olleH .
Queues
A queue is another data structure. A queue is also like a list;
you can add and remove items from it. A queue is also like a
stack because you can only add and remove items in a certain
order. Unlike a stack, where the first item put in is the last out,
a queue is a first-in-first-out data structure (FIFO ): the first
item added is the first item taken out.
Think of a FIFO data structure as a line of people waiting to
buy movie tickets. The first person in line is the first person to
get tickets, the second person in line is the second person to
get tickets, and so on.
In this section, you will build a queue with four methods:
enqueue , dequeue , is_empty , and size.enqueue
adds a new item to the queue; dequeue removes an item
from the queue; is_empty checks returns True if the queue
is empty and False otherwise; and size returns the number
of items in the queue:
1
# http://tinyurl.com/zrg24hj
2
3
4
5
6 class
7 Queue:
8
9 def
10 __init__(
self
11
):
12
13
14 self
.items
15 =
16 []
17
18
19
20
def
21 is_empty(
22 self
):
return
self
.items
=
=
[]
def
enqueue(
self
, item):
self
.items.insert(
0
, item)
def
dequeue(
self
):
return
self
.items.pop()
def
size(
self
):
return
len
(
self
.items)
1
2 # http://tinyurl.com/j3ck9jl
3
4
5
a_queue
=
Queue()
print
(a_queue.is_empty())
>> True
Add items and check the queue’s size:
1
2 # http://tinyurl.com/jzjrg8s
3
4
5
6 a_queue
7 =
Queue()
8
9
10
11 for
i
in
range
(
5
):
a_queue.enqueue(i)
print
(a_queue.size())
>> 5
Remove each item from the queue:
1
2 # http://tinyurl.com/jazkh8b
3
4
5
6 a_queue
7 =
Queue()
8
9
10
11 for
12 i
in
13
range
14 (
15 5
):
16
17
18 a_queue.enqueue(i)
for
i
in
range
(
5
):
print
(a_queue.dequeue())
print
()
print
(a_queue.size())
>> 0
>> 1
>> 2
>> 3
>> 4
>>
>> 0
Ticket Queue
A queue can simulate people waiting in line to buy tickets for
a movie:
1
2 # http://tinyurl.com/jnw56zx
3
4
5
6 import
7 time
8
import
9 random
10
11
12
13 class
Queue:
14
15
16 def
17 __init__(
self
18 ):
19
20
self
21 .items
22 =
[]
23
24
25
26
27 def
28 is_empty(
29 self
):
30
31
32 return
self
33 .items
34 =
=
35
[]
36
37
38
39
40 def
enqueue(
41 self
42 , item):
43
44
self
45 .items.insert(
46 0
, item)
47
48
49
50
51 def
dequeue(
52 self
53 ):
54
55 return
56 self
.items.pop()
57
58
59
60
61 def
size(
self
):
return
len
(
self
.items)
def
simulate_line(
self
,
till_show,
max_time):
pq
=
Queue()
tix_sold
=
[]
for
i
in
range
(
10
):
pq.enqueue(
"person"
+
str
(i))
t_end
=
time.time()\
+
till_show
now
=
time.time()
while
now < t_end \
and
not
pq.is_empty():
now
=
time.time()
r
=
random.\
randint(
0
,
max_time)
time.sleep(r)
person
=
pq.dequeue()
print
(person)
tix_sold.append(person)
return
tix_sold
queue
=
Queue()
sold
=
queue.simulate_line(
5
,
1
)
print
(sold)
>> person0
…
>> [‘person0’, ‘person1’, ‘person2’]
First, you created a function called simulate_line , which
simulates selling tickets to a line of people. The function
accepts two parameters: till_show and max_time . The
first parameter is an integer, representing the number of
seconds until the show starts and there is no time left to buy
tickets. The second parameter is also an integer, representing
the longest amount of time (in seconds) it takes for a person to
buy a ticket.
In the function, you create a new, empty queue and an empty
list. The list will keep track of the people who purchased a
ticket. Next, you fill the queue with one hundred strings,
starting with “person0” and ending with “person99” .
Each string in the queue represents a person in line waiting to
buy a ticket.
The built-in time module has a function called time . It
returns a float that represents the number of seconds it has
been since the epoch , a point in time (January 1st, 1970) used
as a reference. If I call the time function right now, it returns
1481849664.256039 , the number of seconds since the
epoch. If in one second I call it again, the float the function
returns will be incremented by 1 .
The variable t_end finds the result of the time function plus
the number of seconds passed in as the variable till_show .
The combination of the two creates a point in the future.
Your while-loop runs until either the time function
returns a result greater than t_end , or the queue is empty.
Next, you use the sleep function in the built-in time
module to stop Python from doing anything for a random
number of seconds between 0 and max_time . You stop
Python from executing code to simulate the time it takes to sell
a ticket. You stop Python for a random amount of time to
simulate that each ticket sale takes a different amount of time.
After the pause caused by the sleep function, you remove a
string representing a person from the queue and place it into
the tix_sold list, which represents that the person bought a
ticket.
The result of your code is a function that can sell tickets to a
line of people, selling more or fewer tickets depending on the
parameters passed in and random chance.
Vocabulary
Data structure : A format used to store and organize
information.
Popping : Removing an item from a stack.
Pushing : Putting an item onto a stack.
Last-in-first-out data structure : A data structure where the
last item put in is the first item taken out.
LIFO : Last-in-first-out
Stack : A last-in-first-out data structure data structure.
First-in-first-out data structure : A data structure where the
first item added is the first item taken out.
FIFO : First-in-first-out
Queue : A first-in-first-out data structure.
Epoch : A point in time used as a reference.
Challenges
1. Reverse the string “yesterday” using a stack.
2. Use a stack to create a new list with the items in the
following list reversed: [1, 2, 3, 4, 5] .
Solutions: http://tinyurl.com/j7d7nx2 .
Chapter 22. Algorithms
“An algorithm is like a recipe.”
~ Waseem Latif
This chapter is a light introduction to algorithms. An
algorithm is a series of steps that can be followed to solve a
problem. The problem could be searching a list or printing the
lyrics to “99 Bottles of Beer on the Wall.”
FizzBuzz
It’s finally time to learn to solve FizzBuzz, the popular
interview question designed to eliminate candidates:
Write a program that prints the numbers from 1 to 100. But for
multiples of three print “Fizz” instead of the number, and for
the multiples of five print “Buzz.” For multiples of both three
and five print “FizzBuzz.”
To solve this problem, you need a way to check if a number is
a multiple of three, a multiple of five, both, or neither. If a
number is a multiple of three, if you divide it by three, there is
no remainder. The same applies to five. The modulo operator
(% ) returns the remainder. You can solve this problem by
iterating through the numbers and checking if each number is
divisible by both three and five, just three, just five, or neither:
1
# http://tinyurl.com/jroprmn
2
3
4
5
6 def
7 fizz_buzz():
8
9 for
10 i
in
11
range
12 (
13 1
,
14 101
15 ):
16
17 if
i
%
3
=
=
0
\
and
i
%
5
=
=
0
:
print
(
"FizzBuzz"
)
elif
i
%
3
=
=
0
:
print
(
"Fizz"
)
elif
i
%
5
=
=
0
:
print
(
"Buzz"
)
else
:
print
(i)
fizz_buzz()
>> 1
>> 2
>> Fizz
…
You start by iterating through numbers 1 to 100. Then, you
check if the number is divisible by 3 and5 . It is important to
do this first, because if a number is divisible by both, you need
to print FizzBuzz and continue to the next iteration of the
loop. If you checked if a number was divisible by just 3 or 5
first, and found a number that was, you cannot print Fizz or
Buzz and continue to the next iteration of the loop, because
the number could still be divisible by 3 and 5 , in which case
printing Fizz or Buzz is incorrect; you need to print
FizzBuzz .
Once you’ve checked if a number is divisible by 3 and 5 , the
order of these two tests is no longer important, because you
know it is not divisible by both. If the number is divisible by 3
or 5 , you can stop the algorithm and print Fizz or Buzz . If
a number makes it past the first three conditions, you know it
is not divisible by 3 , 5 , or both, and you can print the
number.
Sequential Search
A search algorithm finds information in a data structure like
a list. A sequential search is a simple search algorithm that
checks each item in a data structure to see if the item matches
what it is looking for.
If you were ever playing cards and looking for a specific card
in the deck, you probably did a sequential search to find it.
You went through each card in the deck one by one, and if the
card was not the one you were looking for, you moved on to
the next card. When you finally came to the card you wanted,
you stopped. If you made it through the entire deck without
finding the card, you also stopped, because you realized the
card wasn’t there. Here is an example of a sequential search in
Python:
1
2 # http://tinyurl.com/zer9esp
3
4
5
6 def
7 ss(number_list, n):
8
9 found
10 =
False
11
12
13 for
14 i
in
15 number_list:
16
17
if
i
=
=
n:
found
=
True
break
return
found
numbers
=
range
(
0
,
100
)
s1
=
ss(numbers,
2
)
print
(s1)
s2
=
ss(numbers,
202
)
print
(s2)
>> True
>> False
First, you set the variable found to False . This variable
keeps track of whether or not the algorithm has found the
number you are looking for. Then, you loop through every
number in the list and check if it is that number. If it is, you set
found to True , exit the loop, and return the variable found ,
which is True .
If you do not find the number you are looking for, you
continue to the next number in the list. If you get through the
entire list, you return the variable found . found will be
False if the number isn’t in the list.
Palindrome
A palindrome is a word spelled the same way forward and
backward. You can write an algorithm that checks if a word is
a palindrome by reversing all the letters in the word and
testing if the reversed word and the original word are the
same. If they are, the word is a palindrome:
1
2 # http://tinyurl.com/jffr7pr
3
4
5
6 def
7 palindrome(word):
8
9 word
10 =
word.lower()
return
word[::
-
1
]
=
=
word
print
(palindrome(
"Mother"
))
print
(palindrome(
"Mom"
))
>> False
>> True
The lower method removes uppercase characters from the
word you are testing. Python treats M and m as different
characters, and you want them treated as the same character.
The code word[::-1] reverses the word. [::-1] is
Python’s syntax for returning a slice of an entire iterable in
reverse. You reverse the word so you can compare it to the
original. If they are the same, the function returns True ,
because the word is a palindrome. If not, it returns False .
Anagram
An anagram is a word created by rearranging the letters of
another word. The word iceman is an anagram of cinema,
because you can rearrange the letters in either word to form
the other. You can determine if two words are anagrams by
sorting the letters in each word alphabetically and testing if
they are the same:
1
2 # http://tinyurl.com/hxplj3z
3
4
5
6 def
7 anagram(w1, w2):
8
9 w1
10 =
w1.lower()
11
w2
=
w2.lower()
return
sorted
(w1)
=
=
sorted
(w2)
print
(anagram(
"iceman"
,
"cinema"
))
print
(anagram(
"leaf"
,
"tree"
))
>> True
>> False
First, you call the lower method on both words so that case
does not affect the result. Then, you pass both words into
Python’s sorted method. The sorted method returns the
words sorted in alphabetical order. Finally, you compare the
results. If the sorted words are the same, your algorithm
returns True . Otherwise it returns False .
if
c
in
count_dict:
count_dict[c]
+
=
1
else
:
count_dict[c]
=
1
print
(count_dict)
count_characters(
"Dynasty"
)
Recursion
Recursion is a method of solving problems by breaking the
problem up into smaller and smaller pieces until it can be
easily solved. So far, you’ve solved problems using iterative
algorithms . Iterative algorithms solve problems by repeating
steps over and over, typically using a loop. Recursive
algorithms rely on functions that call themselves. Any
problem you can solve iteratively can be solved recursively;
however, sometimes a recursive algorithm is a more elegant
solution.
You write a recursive algorithm inside of a function. The
function must have a base case : a condition that ends a
recursive algorithm to stop it from continuing forever. Inside
the function, the function calls itself. Each time the function
calls itself, it moves closer to the base case. Eventually, the
base case condition is satisfied, the problem is solved, and the
function stops calling itself. An algorithm that follows these
rules satisfies the three laws of recursion:
1. A recursive algorithm must have a base case.
2. A recursive algorithm must change its state and move
toward the base case.
3. A recursive algorithm must call itself, recursively.14
Here is a recursive algorithm that prints the lyrics to the
popular folk song “99 Bottles of Beer on the Wall”:
1
# http://tinyurl.com/z49qe4s
2
3
4
5
6 def
7 bottles_of_beer(bob):
8
9 """ Prints 99 Bottle
10
11
of Beer on the
12
13
14 Wall lyrics.
15
16
:param bob: Must
17
18
19 be a positive
20
21
integer.
22
23
24 """
25
26 if
27 bob <
28 1
:
29
30
31 print
32 (
"""No more
33
34
35 bottles
36
37
of beer
38
39
on the wall.
No more
bottles of
beer."""
)
return
tmp
=
bob
bob
-
=
1
print
(
"""{} bottles of
beer on the
wall. {} bottles
down, pass it
around, {} bottles
of beer on the
wall.
"""
.
format
(tmp,
tmp,
bob))
bottles_of_beer(bob)
bottles_of_beer(
99
)
3
4
5
6 if
7 bob <
1
8 :
9
10
print
11
(
12 """No more
bottles
of beer
on the wall.
No more
bottles of
beer."""
)
return
1
# http://tinyurl.com/j7zwm8t
2
3
4
bottles_of_beer(bob)
This line ensures that as long as the base case is not satisfied,
your function will call itself. Each time the function calls
itself, it passes itself a parameter that has been decremented by
1 , and thus moves toward the base case. The first time the
function calls itself with this line, it will pass itself 98 as a
parameter, then 97 , then 96 , until finally, it passes itself a
parameter less than 1 , which satisfies the base case and No
more bottles of beer on the wall. No more
bottles of beer . prints. The function then hits the
return keyword, which stops the algorithm.
Recursion is notoriously one of the toughest concepts for new
programmers to grasp. If it is confusing to you at first, don’t
worry—keep practicing. And remember: to understand
recursion; first you must understand recursion.
Vocabulary
Algorithm : A series of steps that can be followed to solve a
problem.
Search algorithm : An algorithm that finds information in a
data structure (like a list).
Sequential search : A simple search algorithm for finding
information in a data structure that checks each item in it to
see if it matches what it is looking for.
Palindrome : A word spelled the same forward and backward.
Anagram : A word created by rearranging the letters of
another word.
Recursion : A method of solving problems by breaking the
problem up into smaller and smaller pieces until it can be
easily solved.
Iterative algorithm : Iterative algorithms solve problems by
repeating steps over and over, typically using a loop.
Recursive algorithm : Recursive algorithms solve problems
using functions that call themselves.
Base case : A condition that ends a recursive algorithm.
Challenge
1. Sign up for an account at http://leetcode.com , and try to
solve three of their easy-level algorithm problems.
Chapter 23.
Best Programming Practices
“Always code as if the guy who ends up maintaining your code
will be a violent psychopath who knows where you live.”
~John Woods
Production code is the code in a product people use. When
you put software into production , it means putting it out in
the world. In this chapter, I cover a few general programming
principles that will help you write production-ready code.
Many of these principles originated in The Pragmatic
Programmer by Andy Hunt and Dave Thomas, a book that
dramatically improved the quality of my code.
DRY
DRY is a programming principle that stands for Don’t Repeat
Yourself. Do not repeat the same, or nearly the same, code in a
program. Instead, put the code into one function that can
handle multiple situations.
Orthogonality
Orthogonality is another important programming principle
popularized by The Pragmatic Programmer . Hunt and
Thomas explain, “In computing, the term has come to signify
a kind of independence or decoupling. Two or more things are
orthogonal if changes in one do not affect any of the others. In
a well-designed system, the database code will be orthogonal
to the user interface: you can change the interface without
affecting the database, and swap databases without changing
the interface.”16 Put this in practice by remembering as much
as possible that “a should not affect b.” If you have two
modules—module a and module b —module a should
not make changes to things in module b , and vice versa. If
you design a system where a affects b; which affects c; which
affects d; things quickly spiral out of control and the system
becomes unmanageable.
Follow Conventions
Taking time to learn the conventions of the new programming
language will help you read code written in the new language
faster. PEP 8 is a set of guidelines for writing Python code,
and you should read it. It includes the rules for extending
Python code to new lines. It’s available at
https://www.python.org/dev/peps/pep-0008/.
Logging
Logging is the practice of recording data when your software
runs. You can use logging to help debug your program and
gain additional insight into what happened when your program
ran. Python comes with a logging module that lets you log to
the console or a file.
When something goes wrong in your program, you don’t want
it to go unnoticed—you should log information about what
happened to review later. Logging is also useful for collecting
and analyzing data. For example, you might set up a web
server to log data—including the date and time—every time it
receives a request. You could store all of your logs in a
database, and create another program to analyze the data and
create a graph displaying the times of day people visit your
website.
The blogger Henrik Warne writes, “One of the differences
between a great programmer and a bad programmer is that a
great programmer adds logging and tools that make it easy to
debug the program when things fail.” You can learn how to
use Python’s logging module at
https://docs.python.org/3/howto/logging.html .
Testing
Testing a program means checking that the program “meets
the requirements that guided its design and development,
responds correctly to all kinds of inputs, performs its functions
within an acceptable time, is sufficiently usable, can be
installed and run in its intended environments, and achieves
the general result its stakeholders desire.”17 To test their
programs, programmers write more programs.
In a production environment, testing is not optional. You
should consider every program you intend to put into
production incomplete until you have written tests for it.
However, if you write a quick program you are never going to
use again, testing might be a waste of time. If you are writing a
program that other people are going to use, you should write
tests. As several famous programmers have said, “Untested
code is broken code.” You can learn how to use Python’s
unittest module at
https://docs.python.org/3/library/unittest.html .
Code Reviews
In a code review someone reads your code and gives
feedback. You should do as many code reviews as you can—
especially as a self-taught programmer. Even if you follow all
the best practices laid out in this chapter, you are going to do
things incorrectly. You need someone with experience to read
over your code and tell you the mistakes you are making, so
you can fix them.
Code Review is a website where you can get code reviews
from a community of programmers. Anyone can go on Code
Review and post their code. Other members of the Stack
Exchange community review your code, give you feedback
about what you did well, and offer helpful suggestions on how
you can improve. You can visit Code Review at
http://codereview.stackexchange.com/ .
Security
Security is an easy subject for the self-taught programmer to
ignore. You probably won’t be asked about security in
interviews, and security is not important for the programs you
write while you are learning to program. However, once you
get your first programming job, you are directly responsible
for the security of the code you write. In this section, I provide
some tips to keep your code safe.
Earlier, you learned to use sudo to issue a command as the
root user. Never run a program from the command-line using
sudo if you don’t have to because a hacker will have root
access if they compromise the program. You should also
disable root logins if you are managing a server. Every hacker
is aware there is a root account, so it is an easy target when
attacking a system.
Always assume user input is malicious. Several kinds of
malicious attacks rely on exploiting programs that accept user
input, so you should also assume all user input is malicious
and program accordingly.
Another strategy for keeping your software secure is to
minimize your attack surface —the different areas of your
program where attackers could extract data or attack your
system. By making your attack area as small as possible, you
reduce the likelihood of vulnerabilities in your program. Some
strategies for minimizing your attack surface: avoid storing
confidential data if you don’t have to, give users the lowest
level of access you can, use as few third-party libraries as
possible (the less code, the less amount of possible exploits),
and get rid of features that are no longer being used (less code,
less exploits).
Avoiding logging in as the root user on your system, not
trusting user input, and minimizing your attack surface are
important steps to making sure your programs are secure. But
these are just starting points. You should always try to think
like a hacker. How would a hacker exploit your code?
Thinking like this can help you find vulnerabilities you
otherwise would overlook. There is a lot more to learn about
security than I can cover in this book, so always be thinking
and learning about it. Bruce Schneier said it best—“Security is
a state of mind.”
Vocabulary
Production code : The code in a product people use.
Production : When you put software into production, it means
putting it out in the world.
DRY : A programming principle that stands for Don’t Repeat
Yourself.
Orthogonality : “In computing, the term has come to signify a
kind of independence or decoupling. Two or more things are
orthogonal if changes in one do not affect any of the others. In
a well-designed system, the database code will be orthogonal
to the user interface: you can change the interface without
affecting the database, and swap databases without changing
the interface.”18
Debugger : A debugger is a program that allows you to stop
the execution of your code and move through your program
line by line so you can see the values of the variables in your
code at different parts of your program.
Logging : The practice of recording data when your software
runs.
Testing : Checking that the program “meets the requirements
that guided its design and development, responds correctly to
all kinds of inputs, performs its functions within an acceptable
time, is sufficiently usable, can be installed and run in its
intended environments, and achieves the general result its
stakeholders desire.” 19
Code review : When someone reads your code and gives you
feedback.
Attack surface : The different areas of your program where
attackers could extract data or attack your system.
Chapter 24.
Your First Programming Job
“Beware of ‘the real world.’ A speaker’s appeal to it is always
an invitation not to challenge his tacit assumptions.”
~ Edsger W. Dijkstra
The final part of this book is dedicated to helping you with
your career. Getting your first programming job requires extra
effort, but if you follow my advice, you should have no
problem. Luckily, once you land your first programming job
and get some experience, when it comes time to look for your
next job, recruiters will be reaching out to you .
Choose a Path
When you apply for a programming job, you will be expected
to know a particular set of technologies, depending on the
domain the job is in. While it’s fine to be a generalist (a
programmer who dabbles in everything) while you are
learning to program, and it is possible to get a job as a
generalist programmer, you should probably focus on an area
of programming you enjoy and become an expert in it.
Focusing on one programming path will make getting a job
easier.
Web and mobile development are two of the most popular
programming paths. There are two specialties within them:
front end and the back end. The front end of an application is
the part you can see—like the GUI of a web app. The back end
is what you can’t see—the part that provides the front end with
data. The titles for open programming jobs will read
something like “Python Backend Programmer,” which means
they are looking for someone who programs the backend of a
website and is familiar with Python. The job description will
list the technologies the ideal candidate will be familiar with,
along with any additional skills needed.
Some companies have a team devoted to the front end and
another to the back end. Other companies only hire full stack
developers—programmers that can work on both the front and
back ends; however, this only applies to companies building
websites or apps.
There are many other programming areas you can work in,
such as security, platform engineering, and data science. Job
descriptions on sites listing programming jobs are a good place
to learn more about the requirements of different areas of
programming. The Python Job Board, found at
https://www.python.org/jobs , is a good place to start. Read the
requirements for a few jobs, as well as the technologies they
use, to get an idea what you need to learn to be competitive for
the type of job you want.
Getting an Interview
Once you’ve gained programming experience through either
open source or freelance work, it’s time to start interviewing.
I’ve found the most efficient way to get an interview is to
focus on LinkedIn. If you don’t have a LinkedIn account,
create one to start networking with potential employers. Write
a summary about yourself at the top of your profile, and make
sure to highlight your programming skills. For example, a lot
of people say something like “Programming Languages:
Python, JavaScript” at the top of their profile, which helps lead
recruiters searching for those keywords to them. Make sure to
put your open source or freelancing experience as your most
recent job.
Once your profile is complete, start connecting with technical
recruiters—there are lots of technical recruiters on LinkedIn.
They are always looking for new talent and will be eager to
connect with you. Once they accept your invitation, reach out
and ask if they are hiring for any open positions.
The Interview
If a recruiter thinks you are a good fit for the role they are
hiring for, they will send you a message on LinkedIn asking to
set up a phone screen. The phone screen will be with the
recruiter, so it is usually non-technical, although I’ve had
recruiters ask me technical questions they’ve memorized the
answer to during first interviews. The conversation is about
the technologies you know, your previous experience, and
figuring out if you would fit in with the company’s culture.
If you do well, you will advance to the second round—a
technical phone screen—where you speak with members of
the engineering team. They will ask you the same questions
from the first interview. However, this time the questions are
accompanied by a technical test over the phone. The engineers
will give you the address of a website where they have posted
programming questions, and ask you to solve them.
If you make it past the second round, you will usually have a
third interview. The third interview is typically in person at the
company’s office. Like the first two, you meet with different
engineers on the team. They ask about your skills and
experience and administer more technical tests. Sometimes
you stay for lunch to see how you interact with the team. The
third round is where the famous whiteboard coding tests
happen. If the company you are interviewing for does
whiteboarding, you will be asked to solve several
programming problems. I recommend buying a whiteboard
and practicing beforehand because solving a programming
problem on a whiteboard is much harder than solving it on a
computer.
Changing Code
By reading this book, you’ve demonstrated you are the type of
person who is constantly looking to improve. Unfortunately,
not everyone on your team will share your enthusiasm for
becoming a better programmer. Many programmers don’t have
the desire to keep learning—they are fine doing things
suboptimally.
Bad code is especially prevalent in startups, where shipping
code quickly is often more important than shipping high-
quality code. If you find yourself in this situation, tread lightly.
Changing someone’s code may hurt their ego. Even worse, if
you spend a lot of time fixing other people’s code, you will not
have enough time to contribute to new projects, and it may
look like you are not working hard enough. The best way to
avoid this environment is to carefully question any company
you are interviewing with about their engineering culture. If
you still find yourself in this situation, it is best to listen to
Edward Yourdon, “If you think your management doesn’t
know what it’s doing or that your organization turns out low-
quality software crap that embarrasses you, then leave.”
Imposter Syndrome
Everyone who programs feels overwhelmed sometimes, and
no matter how hard you work there are going to be things you
don’t know. As a self-taught programmer, it is especially easy
to feel inadequate because someone asked you to do
something you’ve never heard of, or you feel like there are
many concepts in computer science you still do not
understand. These things happen to everyone—not just you.
I was surprised when my friend with a master’s degree in
computer science from Stanford told me he felt this way as
well. He said everyone in his program dealt with imposter
syndrome. He noticed they reacted one of two ways: they
either stayed humble and were willing to admit when they
didn’t know something—and worked to learn it, or they
pretended they knew everything (when they didn’t) and stifled
their learning. Remember you got to where you are by
working hard, and it’s OK if you don’t know everything,
nobody does. Just stay humble, and relentlessly study anything
you don’t understand, and you will be unstoppable.
Chapter 26.
Further Learning
“The best programmers are not marginally better than merely
good ones. They are an order-of-magnitude better, measured
by whatever standard: conceptual creativity, speed, ingenuity
of design, or problem-solving ability.”
~ Randall E. Stross
The article “ABC: Always Be Coding” by David Byttow gives
great advice on how to get a job as a software engineer. The
title says it all—always be coding. You can find the article at
https://medium.com/always-be-coding/abc-always-be-coding-
d5f8051afce2#.2hjho0px7 . If you combine ABC with a new
acronym I made up—ABL—always be learning—you are sure
to have an exceptional career. In this chapter, I am going to
review some of the programming resources I’ve found helpful.
The Classics
There are a few programming books that are considered must-
reads. The Pragmatic Programmer by Andy Hunt and Dave
Thomas; Design Patterns by Erich Gamma, John Vlissides,
Ralph Johnson, and Richard Helm (design patterns are an
important subject I didn’t get a chance to cover); Code
Complete by Steve McConnell; Compilers: Principles,
Techniques, and Tools , by Alfred Aho, Jeffrey Ullman,
Monica S. Lam, and Ravi Sethi; and Introduction to
Algorithms by the MIT Press. I also highly recommend
Problem Solving with Data Structures and Algorithms , a free,
interactive, excellent introduction to algorithms by Bradley N.
Miller and David L. Ranum and much easier to understand
than MIT’s Introduction to Algorithms .
Online Classes
Online coding classes are another way to improve your
programming skills. You can find all of my class
recommendations at http://theselftaughtprogrammer.io/courses
.
Hacker News
Hacker News is a platform for user-submitted news hosted on
the technology incubator Y Combinator’s website, found at
https://news.ycombinator.com . It will help you keep up to
date with the newest trends and technologies.
Chapter 27.
Next Steps
“Love the little trade which thou hast learned, and be content
therewith.”
~ Marcus Aurelius
First of all—thank you for purchasing this book. I hope it’s
helped you become a better programmer. Now that you’re
finished, it’s time for you to get down to business. Where do
you go from here? Data structures and algorithms. Get on
LeetCode and practice those algorithms. Then practice them
some more! In this chapter, I give some final thoughts on how
you can continue to improve as a programmer (once you
finished practicing writing algorithms).
Find a Mentor
A mentor will help take your programming skills to the next
level. One of the hard things about learning to program is that
there are so many things you can do suboptimally without
knowing it. I mentioned earlier you can help combat this by
doing code reviews. A mentor can do code reviews with you
to help improve your coding process, recommend books, and
teach you programming concepts you don’t understand.
Strive to Go Deep
There is a concept in programming called a “black box,”
which refers to something you use but do not understand how
it works. When you first start programming, everything is a
black box. One of the best ways to get better at programming
is to open up every black box you find and try to understand
how it works. One of my friends told me it was a major “aha”
moment when he realized the command-line itself is a
program. Opening up a black box is what I call going deep.
Writing this book helped me go deep. There were certain
concepts I thought I understood, only to find out I couldn’t
explain them. I had to go deep. Don’t stop at just one answer,
read all the explanations on a topic you can find. Ask
questions and read differing opinions online.
Another way to go deep is to build things you want to
understand better. Having trouble understanding version
control? Build a simple version control system in your free
time. Taking the time to do a project like that is well worth the
investment—it will improve your understanding of whatever
you are struggling with.
Other Advice
I once came across a forum topic discussing different ways to
become a better programmer. The top voted answer was
surprising: Do things other than programming. I’ve found this
to be true—reading books like The Talent Code by Daniel
Coyle has made me a better programmer because he lays out
exactly what you need to do to master any skill. Keep your eye
out for things outside of programming you can bring to your
programming game.
The last piece of advice I will leave you with is to spend as
much time as you can reading other people’s code. It is one of
the best ways to improve as a programmer. When you are
learning, make sure to strike a balance between writing and
reading code. Reading other people’s code is going to be
difficult at first, but it is important because you can learn so
much from other programmers.
I hope you enjoyed reading this book as much as I enjoyed
writing it. Please feel free to email me at
cory@theselftaughtprogrammer.io for any reason. I also have
a programming newsletter you can sign up for at
http://theselftaughprogrammer.io and a Facebook group
located
at https://www.facebook.com/groups/selftaughtprogrammers
where you can get in touch with me and a community of other
people learning to program. If you like this book, please
consider leaving a review on Amazon at
https://www.amazon.com/dp/B01M01YDQA#customerRevie
ws , it helps get this book in the hands of more people, and I
appreciate every review I receive. Best of luck on the rest of
your journey.
Acknowledgements
I want to thank everyone that helped make this book possible.
My parents, Abby and James Althoff, were so supportive
during the entire process. My Dad went through every page of
the book and gave me amazing feedback. I couldn’t have made
this happen without him. My girlfriend, Lauren Wordell, put
up with me working on this book at all times. I want to thank
my incredibly talented illustrator Blake Bowers; my editors
Steve Bush, Madeline Luce, Pam Walatka and Lawrence
Sanfilippo; and my friend Antoine Sindu—several of our
discussions made it into the book. I also want to thank Randee
Fenner, who supported the project on Kickstarter and
introduced me to Pam. Shoutout to my former boss Anzar
Afaq, who was incredibly supportive when I joined his team at
eBay. A big thank you to all of the beta readers who read the
book early and gave me feedback. Finally, I want to thank
everyone on Kickstarter that backed this project, especially Jin
Chun, Sunny Lee, and Leigh Forrest. Thank you all so much!
Citations
1.http://www.infoworld.com/article/2908474/application-
development/stack-overflow-survey-finds-nearly-half-have-
no-degree-in-computer-science.html
2.http://www.wsj.com/articles/computer-programming-is-a-
trade-lets-act-like-it-1407109947?mod=e2fb
3.https://en.wikipedia.org/wiki/Syntax
4.https://en.wikipedia.org/wiki/Syntax
5.https://www.tutorialspoint.com/python/python_files_io.htm
6.https://maryrosecook.com/blog/post/a-practical-introduction-
to-functional-programming
7.http://whatis.techtarget.com/definition/abstraction
8.http://stackoverflow.com/questions/1031273/what-is-
polymorphism-what-is-it-for-and-how-is-it-used
9.http://stackoverflow.com/questions/1031273/what-is-
polymorphism-what-is-it-for-and-how-is-it-used
10.http://whatis.techtarget.com/definition/abstraction
11.https://en.wikipedia.org/wiki/Regular_expression
12.http://tldp.org/LDP/Bash-Beginners-
Guide/html/sect_04_01.html
13.https://en.wikipedia.org/wiki/Regular_expression
14.https://interactivepython.org/runestone/static/pythonds/Rec
ursion/TheThreeLawsofRecursion.html