Sie sind auf Seite 1von 26

Beginner's Python

Lists (cont.) Dictionaries


Dictionaries store connections between pieces of
List comprehensions information. Each item in a dictionary is a key-value pair.

Cheat Sheet squares = [x**2 for x in range(1, 11)]


Slicing a list
A simple dictionary
alien = {'color': 'green', 'points': 5}
finishers = ['sam', 'bob', 'ada', 'bea']
Accessing a value
Variables and Strings first_two = finishers[:2]
print(f"The alien's color is {alien['color']}")
Variables are used to store values. A string is a series of Copying a list
characters, surrounded by single or double quotes. Adding a new key-value pair
copy_of_bikes = bikes[:]
Hello world alien['x_position'] = 0
print("Hello world!")
Tuples Looping through all key-value pairs
Hello world with a variable Tuples are similar to lists, but the items in a tuple can't be fav_numbers = {'eric': 17, 'ever': 4}
modified. for name, number in fav_numbers.items():
msg = "Hello world!"
print(f"{name} loves {number}")
print(msg) Making a tuple
f-strings (using variables in strings) dimensions = (1920, 1080)
Looping through all keys
fav_numbers = {'eric': 17, 'ever': 4}
first_name = 'albert'
for name in fav_numbers.keys():
last_name = 'einstein' If statements print(f"{name} loves a number")
full_name = f"{first_name} {last_name}" If statements are used to test for particular conditions and
print(full_name) respond appropriately. Looping through all the values
Conditional tests fav_numbers = {'eric': 17, 'ever': 4}
Lists for number in fav_numbers.values():
equals x == 42 print(f"{number} is a favorite")
A list stores a series of items in a particular order. You
not equal x != 42
access items using an index, or within a loop.
greater than x > 42
Make a list or equal to x >= 42 User input
less than x < 42 Your programs can prompt the user for input. All input is
bikes = ['trek', 'redline', 'giant'] or equal to x <= 42 stored as a string.
Get the first item in a list Conditional test with lists Prompting for a value
first_bike = bikes[0] 'trek' in bikes name = input("What's your name? ")
Get the last item in a list 'surly' not in bikes print(f"Hello, {name}!")
last_bike = bikes[-1] Assigning boolean values Prompting for numerical input
Looping through a list game_active = True age = input("How old are you? ")
can_edit = False age = int(age)
for bike in bikes:
print(bike) A simple if test
pi = input("What's the value of pi? ")
Adding items to a list if age >= 18: pi = float(pi)
print("You can vote!")
bikes = []
bikes.append('trek') If-elif-else statements
bikes.append('redline')
bikes.append('giant')
if age < 4:
ticket_price = 0
Python Crash Course
Making numerical lists elif age < 18: A Hands-On, Project-Based
ticket_price = 10 Introduction to Programming
squares = [] else:
for x in range(1, 11): ticket_price = 15 nostarch.com/pythoncrashcourse2e
squares.append(x**2)
While loops Classes Working with files
A while loop repeats a block of code as long as a certain A class defines the behavior of an object and the kind of Your programs can read from files and write to files. Files
condition is true. information an object can store. The information in a class are opened in read mode ('r') by default, but can also be
is stored in attributes, and functions that belong to a class opened in write mode ('w') and append mode ('a').
A simple while loop are called methods. A child class inherits the attributes and
methods from its parent class. Reading a file and storing its lines
current_value = 1
while current_value <= 5: filename = 'siddhartha.txt'
Creating a dog class
print(current_value) with open(filename) as file_object:
current_value += 1 class Dog(): lines = file_object.readlines()
"""Represent a dog."""
Letting the user choose when to quit for line in lines:
msg = '' def __init__(self, name): print(line)
while msg != 'quit': """Initialize dog object."""
self.name = name Writing to a file
msg = input("What's your message? ")
print(msg) filename = 'journal.txt'
def sit(self): with open(filename, 'w') as file_object:
"""Simulate sitting.""" file_object.write("I love programming.")
Functions print(f"{self.name} is sitting.")
Functions are named blocks of code, designed to do one Appending to a file
specific job. Information passed to a function is called an my_dog = Dog('Peso')
argument, and information received by a function is called a filename = 'journal.txt'
parameter. with open(filename, 'a') as file_object:
print(f"{my_dog.name} is a great dog!") file_object.write("\nI love making games.")
A simple function my_dog.sit()

def greet_user(): Inheritance Exceptions


"""Display a simple greeting.""" class SARDog(Dog): Exceptions help you respond appropriately to errors that
print("Hello!") """Represent a search dog.""" are likely to occur. You place code that might cause an
error in the try block. Code that should run in response to
greet_user() def __init__(self, name): an error goes in the except block. Code that should run only
Passing an argument """Initialize the sardog.""" if the try block was successful goes in the else block.
super().__init__(name)
def greet_user(username): Catching an exception
"""Display a personalized greeting.""" def search(self): prompt = "How many tickets do you need? "
print(f"Hello, {username}!") """Simulate searching.""" num_tickets = input(prompt)
print(f"{self.name} is searching.")
greet_user('jesse') try:
my_dog = SARDog('Willie') num_tickets = int(num_tickets)
Default values for parameters
except ValueError:
def make_pizza(topping='bacon'): print(f"{my_dog.name} is a search dog.") print("Please try again.")
"""Make a single-topping pizza.""" my_dog.sit() else:
print(f"Have a {topping} pizza!") my_dog.search() print("Your tickets are printing.")

make_pizza()
make_pizza('pepperoni')
Infinite Skills Zen of Python
If you had infinite programming skills, what would you Simple is better than complex
Returning a value build?
If you have a choice between a simple and a complex
def add_numbers(x, y): As you're learning to program, it's helpful to think solution, and both work, use the simple solution. Your
"""Add two numbers and return the sum.""" about the real-world projects you'd like to create. It's
return x + y code will be easier to maintain, and it will be easier
a good habit to keep an "ideas" notebook that you for you and others to build on that code later on.
can refer to whenever you want to start a new project.
sum = add_numbers(3, 5)
print(sum)
If you haven't done so already, take a few minutes
and describe three projects you'd like to create. More cheat sheets available at
ehmatthes.github.io/pcc_2e/
Beginner's Python Adding elements
You can add elements to the end of a list, or you can insert
Sorting a list
The sort() method changes the order of a list

Cheat Sheet - Lists


them wherever you like in a list. permanently. The sorted() function returns a copy of the
list, leaving the original list unchanged. You can sort the
Adding an element to the end of the list items in a list in alphabetical order, or reverse alphabetical
users.append('amy') order. You can also reverse the original order of the list.
Keep in mind that lowercase and uppercase letters may
Starting with an empty list affect the sort order.
What are lists?
users = [] Sorting a list permanently
A list stores a series of items in a particular order. users.append('val')
Lists allow you to store sets of information in one users.append('bob') users.sort()
place, whether you have just a few items or millions users.append('mia')
Sorting a list permanently in reverse alphabetical
of items. Lists are one of Python's most powerful Inserting elements at a particular position order
features readily accessible to new programmers, and
they tie together many important concepts in users.insert(0, 'joe') users.sort(reverse=True)
programming. users.insert(3, 'bea')
Sorting a list temporarily
Removing elements print(sorted(users))
Defining a list You can remove elements by their position in a list, or by print(sorted(users, reverse=True))
Use square brackets to define a list, and use commas to the value of the item. If you remove an item by its value,
separate individual items in the list. Use plural names for Reversing the order of a list
Python removes only the first item that has that value.
lists, to make your code easier to read. users.reverse()
Deleting an element by its position
Making a list
del users[-1] Looping through a list
users = ['val', 'bob', 'mia', 'ron', 'ned']
Removing an item by its value Lists can contain millions of items, so Python provides an
efficient way to loop through all the items in a list. When
Accessing elements users.remove('mia') you set up a loop, Python pulls each item from the list one
Individual elements in a list are accessed according to their at a time and stores it in a temporary variable, which you
provide a name for. This name should be the singular
position, called the index. The index of the first element is Popping elements
0, the index of the second element is 1, and so forth. version of the list name.
If you want to work with an element that you're removing The indented block of code makes up the body of the
Negative indices refer to items at the end of the list. To get from the list, you can "pop" the element. If you think of the
a particular element, write the name of the list and then the loop, where you can work with each individual item. Any
list as a stack of items, pop() takes an item off the top of lines that are not indented run after the loop is completed.
index of the element in square brackets. the stack. By default pop() returns the last element in the
Getting the first element list, but you can also pop elements from any position in the Printing all items in a list
list.
first_user = users[0] for user in users:
Pop the last item from a list print(user)
Getting the second element
most_recent_user = users.pop() Printing a message for each item, and a separate
second_user = users[1] print(most_recent_user) message afterwards
Getting the last element Pop the first item in a list for user in users:
print(f"Welcome, {user}!")
newest_user = users[-1] first_user = users.pop(0)
print(first_user) print("Welcome, we're glad to see you all!")
Modifying individual items
Once you've defined a list, you can change individual List length
elements in the list. You do this by referring to the index of The len() function returns the number of items in a list. Python Crash Course
the item you want to modify.
Find the length of a list A Hands-On, Project-Based
Changing an element num_users = len(users) Introduction to Programming
users[0] = 'valerie' print(f"We have {num_users} users.")
users[-2] = 'ronald' nostarch.com/pythoncrashcourse2e
The range() function Copying a list Tuples
You can use the range() function to work with a set of To copy a list make a slice that starts at the first item and A tuple is like a list, except you can't change the values in a
numbers efficiently. The range() function starts at 0 by ends at the last item. If you try to copy a list without using tuple once it's defined. Tuples are good for storing
default, and stops one number below the number passed to this approach, whatever you do to the copied list will affect information that shouldn't be changed throughout the life of
it. You can use the list() function to efficiently generate a the original list as well. a program. Tuples are usually designated by parentheses.
large list of numbers. (You can overwrite an entire tuple, but you can't change the
Making a copy of a list individual elements in a tuple.)
Printing the numbers 0 to 1000 finishers = ['kai', 'abe', 'ada', 'gus', 'zoe'] Defining a tuple
for number in range(1001): copy_of_finishers = finishers[:]
print(number) dimensions = (800, 600)

Printing the numbers 1 to 1000 List comprehensions Looping through a tuple


You can use a loop to generate a list based on a range of for dimension in dimensions:
for number in range(1, 1001):
numbers or on another list. This is a common operation, so print(dimension)
print(number)
Python offers a more efficient way to do it. List
Making a list of numbers from 1 to a million comprehensions may look complicated at first; if so, use the Overwriting a tuple
for loop approach until you're ready to start using dimensions = (800, 600)
numbers = list(range(1, 1000001)) comprehensions. print(dimensions)
To write a comprehension, define an expression for the
Simple statistics values you want to store in the list. Then write a for loop to
dimensions = (1200, 900)
generate input values needed to make the list.
There are a number of simple statistical operations you can
run on a list containing numerical data. Using a loop to generate a list of square numbers
Visualizing your code
Finding the minimum value in a list squares = [] When you're first learning about data structures such as
ages = [93, 99, 66, 17, 85, 1, 35, 82, 2, 77] for x in range(1, 11): lists, it helps to visualize how Python is working with the
square = x**2 information in your program. pythontutor.com is a great tool
youngest = min(ages)
squares.append(square) for seeing how Python keeps track of the information in a
Finding the maximum value list. Try running the following code on pythontutor.com, and
Using a comprehension to generate a list of square
then run your own code.
ages = [93, 99, 66, 17, 85, 1, 35, 82, 2, 77] numbers
oldest = max(ages) Build a list and print the items in the list
squares = [x**2 for x in range(1, 11)]
Finding the sum of all values dogs = []
Using a loop to convert a list of names to upper case dogs.append('willie')
ages = [93, 99, 66, 17, 85, 1, 35, 82, 2, 77]
names = ['kai', 'abe', 'ada', 'gus', 'zoe'] dogs.append('hootz')
total_years = sum(ages)
dogs.append('peso')
upper_names = [] dogs.append('goblin')
Slicing a list for name in names:
You can work with any set of elements from a list. A portion upper_names.append(name.upper()) for dog in dogs:
of a list is called a slice. To slice a list start with the index of print(f"Hello {dog}!")
Using a comprehension to convert a list of names to print("I love these dogs!")
the first item you want, then add a colon and the index after
the last item you want. Leave off the first index to start at upper case
the beginning of the list, and leave off the last index to slice print("\nThese were my first two dogs:")
names = ['kai', 'abe', 'ada', 'gus', 'zoe']
through the end of the list. old_dogs = dogs[:2]
upper_names = [name.upper() for name in names] for old_dog in old_dogs:
Getting the first three items print(old_dog)
finishers = ['kai', 'abe', 'ada', 'gus', 'zoe']
first_three = finishers[:3] Styling your code del dogs[0]
Readability counts dogs.remove('peso')
Getting the middle three items print(dogs)
• Use four spaces per indentation level.
middle_three = finishers[1:4]
• Keep your lines to 79 characters or fewer.
Getting the last three items • Use single blank lines to group parts of your
program visually.
More cheat sheets available at
last_three = finishers[-3:] ehmatthes.github.io/pcc_2e/
Beginner's Python
Adding new key-value pairs Looping through a dictionary
You can store as many key-value pairs as you want in a You can loop through a dictionary in three ways: you can
dictionary, until your computer runs out of memory. To add loop through all the key-value pairs, all the keys, or all the

Cheat Sheet – a new key-value pair to an existing dictionary give the name
of the dictionary and the new key in square brackets, and
set it equal to the new value.
values.
Dictionaries keep track of the order in which key-value
pairs are added. If you want to process the information in a

Dictionaries This also allows you to start with an empty dictionary and
add key-value pairs as they become relevant.
different order, you can sort the keys in your loop.
Looping through all key-value pairs
Adding a key-value pair # Store people's favorite languages.
alien_0 = {'color': 'green', 'points': 5} fav_languages = {
What are dictionaries? 'jen': 'python',
alien_0['x'] = 0 'sarah': 'c',
Python's dictionaries allow you to connect pieces of
alien_0['y'] = 25 'edward': 'ruby',
related information. Each piece of information in a 'phil': 'python',
alien_0['speed'] = 1.5
dictionary is stored as a key-value pair. When you }
provide a key, Python returns the value associated Adding to an empty dictionary
with that key. You can loop through all the key-value alien_0 = {} # Show each person's favorite language.
pairs, all the keys, or all the values. alien_0['color'] = 'green' for name, language in fav_languages.items():
alien_0['points'] = 5 print(f"{name}: {language}")
Defining a dictionary Looping through all the keys
Use curly braces to define a dictionary. Use colons to Modifying values # Show everyone who's taken the survey.
connect keys and values, and use commas to separate You can modify the value associated with any key in a for name in fav_languages.keys():
individual key-value pairs. dictionary. To do so give the name of the dictionary and print(name)
enclose the key in square brackets, then provide the new
Making a dictionary Looping through all the values
value for that key.
alien_0 = {'color': 'green', 'points': 5} # Show all the languages that have been chosen.
Modifying values in a dictionary
for language in fav_languages.values():
alien_0 = {'color': 'green', 'points': 5}
Accessing values print(language)
print(alien_0)
To access the value associated with an individual key give Looping through all the keys in reverse order
the name of the dictionary and then place the key in a set of # Change the alien's color and point value.
square brackets. If the key you're asking for is not in the # Show each person's favorite language,
alien_0['color'] = 'yellow' # in reverse order by the person's name.
dictionary, an error will occur. alien_0['points'] = 10
You can also use the get() method, which returns None for name in sorted(fav_languages.keys(),
print(alien_0) reverse=True):
instead of an error if the key doesn't exist. You can also
specify a default value to use if the key is not in the print(f"{name}: language")
dictionary. Removing key-value pairs
You can remove any key-value pair you want from a
Getting the value associated with a key
dictionary. To do so use the del keyword and the dictionary
Dictionary length
alien_0 = {'color': 'green', 'points': 5} name, followed by the key in square brackets. This will You can find the number of key-value pairs in a dictionary.
delete the key and its associated value. Finding a dictionary's length
print(alien_0['color'])
print(alien_0['points']) Deleting a key-value pair num_responses = len(fav_languages)
alien_0 = {'color': 'green', 'points': 5}
Getting the value with get()
print(alien_0)
alien_0 = {'color': 'green'}
del alien_0['points'] Python Crash Course
alien_color = alien_0.get('color') print(alien_0) A Hands-On, Project-Based
alien_points = alien_0.get('points', 0)
Introduction to Programming
print(alien_color)
Visualizing dictionaries
print(alien_points) Try running some of these examples on pythontutor.com. nostarch.com/pythoncrashcourse2e
Nesting ‒ A list of dictionaries Nesting ‒ Lists in a dictionary Dictionary Comprehensions
It's sometimes useful to store a set of dictionaries in a list; Storing a list inside a dictionary allows you to associate A comprehension is a compact way of generating a
this is called nesting. more than one value with each key. dictionary, similar to a list comprehension.
To make a dictionary comprehension, define an
Storing dictionaries in a list Storing lists in a dictionary expression for the key-value pairs you want to make. Then
# Start with an empty list. # Store multiple languages for each person. write a for loop to generate the values that will feed into this
users = [] fav_languages = { expression.
The zip() function matches each item in one list to each
'jen': ['python', 'ruby'],
# Make a new user, and add them to the list. 'sarah': ['c'], item in a second list. It can be used to make a dictionary
from two lists.
new_user = { 'edward': ['ruby', 'go'],
'last': 'fermi', 'phil': ['python', 'haskell'], Using loop to make a dictionary
'first': 'enrico', }
'username': 'efermi', squares = {}
} # Show all responses for each person. for x in range(5):
users.append(new_user) for name, langs in fav_languages.items(): squares[x] = x**2
print(f"{name}: ") Using a dictionary comprehension
# Make another new user, and add them as well. for lang in langs:
new_user = { print(f"- {lang}") squares = {x:x**2 for x in range(5)}
'last': 'curie',
'first': 'marie',
Using zip() to make a dictionary
'username': 'mcurie',
Nesting ‒ A dictionary of dictionaries
group_1 = ['kai', 'abe', 'ada', 'gus', 'zoe']
} You can store a dictionary inside another dictionary. In this group_2 = ['jen', 'eva', 'dan', 'isa', 'meg']
users.append(new_user) case each value associated with a key is itself a dictionary.
Storing dictionaries in a dictionary pairings = {name:name_2
# Show all information about each user. for name, name_2 in zip(group_1, group_2)}
for user_dict in users: users = {
for k, v in user_dict.items(): 'aeinstein': {
Generating a million dictionaries
print(f"{k}: {v}") 'first': 'albert',
'last': 'einstein', You can use a loop to generate a large number of
print("\n")
'location': 'princeton', dictionaries efficiently, if all the dictionaries start out with
You can also define a list of dictionaries directly, }, similar data.
without using append(): 'mcurie': { A million aliens
'first': 'marie',
# Define a list of users, where each user aliens = []
'last': 'curie',
# is represented by a dictionary.
users = [ 'location': 'paris',
}, # Make a million green aliens, worth 5 points
{ # each. Have them all start in one row.
'last': 'fermi', }
for alien_num in range(1000000):
'first': 'enrico', new_alien = {}
'username': 'efermi', for username, user_dict in users.items():
print("\nUsername: " + username) new_alien['color'] = 'green'
}, new_alien['points'] = 5
full_name = user_dict['first'] + " "
{ new_alien['x'] = 20 * alien_num
full_name += user_dict['last']
'last': 'curie', new_alien['y'] = 0
location = user_dict['location']
'first': 'marie', aliens.append(new_alien)
'username': 'mcurie',
print(f"\tFull name: {full_name.title()}")
}, # Prove the list contains a million aliens.
] print(f"\tLocation: {location.title()}")
num_aliens = len(aliens)
# Show all information about each user. Levels of nesting print("Number of aliens created:")
for user_dict in users:
Nesting is extremely useful in certain situations. However, print(num_aliens)
for k, v in user_dict.items(): be aware of making your code overly complex. If you're
print(f"{k}: {v}") nesting items much deeper than what you see here there
print("\n") are probably simpler ways of managing your data, such as More cheat sheets available at
using classes. ehmatthes.github.io/pcc_2e/
Beginner's Python
Numerical comparisons If statements
Testing numerical values is similar to testing string values. Several kinds of if statements exist. Your choice of which
to use depends on the number of conditions you need to

Cheat Sheet –
Testing equality and inequality test. You can have as many elif blocks as you need, and
>>> age = 18 the else block is always optional.

If Statements
>>> age == 18
True
Simple if statement
>>> age != 18 age = 19

and While Loops


False
if age >= 18:
Comparison operators print("You're old enough to vote!")
>>> age = 19
>>> age < 21
If-else statements
True age = 17
What are if statements? What are while loops? >>> age <= 21
True if age >= 18:
If statements allow you to examine the current state >>> age > 21 print("You're old enough to vote!")
of a program and respond appropriately to that state. False else:
You can write a simple if statement that checks one >>> age >= 21 print("You can't vote yet.")
False
condition, or you can create a complex series of if The if-elif-else chain
statements that identify the exact conditions you're
Checking multiple conditions age = 12
looking for.
You can check multiple conditions at the same time. The if age < 4:
While loops run as long as certain conditions remain and operator returns True if all the conditions listed are price = 0
true. You can use while loops to let your programs True. The or operator returns True if any condition is True. elif age < 18:
run as long as your users want them to. Using and to check multiple conditions price = 5
else:
>>> age_0 = 22 price = 10
Conditional Tests >>> age_1 = 18
A conditional test is an expression that can be evaluated as >>> age_0 >= 21 and age_1 >= 21 print(f"Your cost is ${price}.")
True or False. Python uses the values True and False to False
decide whether the code in an if statement should be >>> age_1 = 23
executed. >>> age_0 >= 21 and age_1 >= 21 Conditional tests with lists
True You can easily test whether a certain value is in a list. You
Checking for equality
A single equal sign assigns a value to a variable. A double equal
can also test whether a list is empty before trying to loop
Using or to check multiple conditions through the list.
sign (==) checks whether two values are equal.
>>> age_0 = 22 Testing if a value is in a list
>>> car = 'bmw'
>>> age_1 = 18
>>> car == 'bmw' >>> players = ['al', 'bea', 'cyn', 'dale']
>>> age_0 >= 21 or age_1 >= 21
True >>> 'al' in players
True
>>> car = 'audi' True
>>> age_0 = 18
>>> car == 'bmw' >>> 'eric' in players
>>> age_0 >= 21 or age_1 >= 21
False False
False
Ignoring case when making a comparison
>>> car = 'Audi' Boolean values
>>> car.lower() == 'audi'
True
A boolean value is either True or False. Variables with
boolean values are often used to keep track of certain
Python Crash Course
conditions within a program. A Hands-On, Project-Based
Checking for inequality
Simple boolean values Introduction to Programming
>>> topping = 'mushrooms'
>>> topping != 'anchovies' game_active = True nostarch.com/pythoncrashcourse2e
True can_edit = False
Conditional tests with lists (cont.) While loops (cont.) While loops (cont.)
Testing if a value is not in a list Letting the user choose when to quit Using continue in a loop
banned_users = ['ann', 'chad', 'dee'] prompt = "\nTell me something, and I'll " banned_users = ['eve', 'fred', 'gary', 'helen']
user = 'erin' prompt += "repeat it back to you."
prompt += "\nEnter 'quit' to end the program. " prompt = "\nAdd a player to your team."
if user not in banned_users: prompt += "\nEnter 'quit' when you're done. "
print("You can play!") message = ""
while message != 'quit': players = []
Checking if a list is empty message = input(prompt) while True:
players = [] player = input(prompt)
if message != 'quit': if player == 'quit':
if players: print(message) break
for player in players: elif player in banned_users:
Using a flag print(f"{player} is banned!")
print(f"Player: {player.title()}")
else: prompt = "\nTell me something, and I'll " continue
print("We have no players yet!") prompt += "repeat it back to you." else:
prompt += "\nEnter 'quit' to end the program. " players.append(player)

Accepting input active = True print("\nYour team:")


You can allow your users to enter input using the input() while active: for player in players:
statement. All input is initially stored as a string. message = input(prompt) print(player)
If you want to accept numerical input, you'll need to
convert the input string value to a numerical type. if message == 'quit': Avoiding infinite loops
active = False
Simple input Every while loop needs a way to stop running so it won't
else: continue to run forever. If there's no way for the condition to
name = input("What's your name? ") print(message) become False, the loop will never stop running. You can
print(f"Hello, {name}.") usually press Ctrl-C to stop an infinite loop.
Using break to exit a loop
Accepting numerical input using int() An infinite loop
prompt = "\nWhat cities have you visited?"
age = input("How old are you? ") prompt += "\nEnter 'quit' when you're done. " while True:
age = int(age) name = input("\nWho are you? ")
while True: print(f"Nice to meet you, {name}!")
if age >= 18: city = input(prompt)
print("\nYou can vote!")
Removing all instances of a value from a list
else: if city == 'quit':
print("\nYou can't vote yet.") break The remove() method removes a specific value from a list,
else: but it only removes the first instance of the value you
Accepting numerical input using float()
print(f"I've been to {city}!") provide. You can use a while loop to remove all instances
tip = input("How much do you want to tip? ") of a particular value.
tip = float(tip) Accepting input with Sublime Text Removing all cats from a list of pets
Sublime Text doesn't run programs that prompt the user for pets = ['dog', 'cat', 'dog', 'fish', 'cat',
While loops input. You can use Sublime Text to write programs that 'rabbit', 'cat']
A while loop repeats a block of code as long as a condition prompt for input, but you'll need to run these programs from print(pets)
is True. a terminal.
while 'cat' in pets:
Counting to 5 pets.remove('cat')
Breaking out of loops
current_number = 1 You can use the break statement and the continue
print(pets)
statement with any of Python's loops. For example you can
while current_number <= 5: use break to quit a for loop that's working through a list or a
print(current_number)
current_number += 1
dictionary. You can use continue to skip over certain items More cheat sheets available at
when looping through a list or dictionary as well. ehmatthes.github.io/pcc_2e/
Beginner's Python
Positional and keyword arguments Return values
The two main kinds of arguments are positional and A function can return a value or a set of values. When a
keyword arguments. When you use positional arguments function returns a value, the calling line should provide a

Cheat Sheet – Python matches the first argument in the function call with
the first parameter in the function definition, and so forth.
With keyword arguments, you specify which parameter
variable which the return value can be assigned to. A
function stops running when it reaches a return statement.

Functions each argument should be assigned to in the function call. Returning a single value
When you use keyword arguments, the order of the def get_full_name(first, last):
arguments doesn't matter. """Return a neatly formatted full name."""
Using positional arguments full_name = f"{first} {last}"
return full_name.title()
What are functions? def describe_pet(animal, name):
Functions are named blocks of code designed to do """Display information about a pet.""" musician = get_full_name('jimi', 'hendrix')
print(f"\nI have a {animal}.") print(musician)
one specific job. Functions allow you to write code
print(f"Its name is {name}.")
once that can then be run whenever you need to Returning a dictionary
accomplish the same task. Functions can take in the describe_pet('hamster', 'harry') def build_person(first, last):
information they need, and return the information they describe_pet('dog', 'willie') """Return a dictionary of information
generate. Using functions effectively makes your about a person.
programs easier to write, read, test, and fix. Using keyword arguments
"""
def describe_pet(animal, name): person = {'first': first, 'last': last}
Defining a function """Display information about a pet.""" return person
The first line of a function is its definition, marked by the print(f"\nI have a {animal}.")
keyword def. The name of the function is followed by a set print(f"Its name is {name}.") musician = build_person('jimi', 'hendrix')
of parentheses and a colon. A docstring, in triple quotes, print(musician)
describes what the function does. The body of a function is describe_pet(animal='hamster', name='harry')
describe_pet(name='willie', animal='dog') Returning a dictionary with optional values
indented one level.
To call a function, give the name of the function followed def build_person(first, last, age=None):
by a set of parentheses. Default values """Return a dictionary of information
about a person.
Making a function You can provide a default value for a parameter. When
function calls omit this argument the default value will be """
def greet_user(): used. Parameters with default values must be listed after person = {'first': first, 'last': last}
"""Display a simple greeting.""" parameters without default values in the function's definition if age:
print("Hello!") so positional arguments can still work correctly. person['age'] = age
return person
greet_user() Using a default value
musician = build_person('jimi', 'hendrix', 27)
def describe_pet(name, animal='dog'):
print(musician)
Passing information to a function """Display information about a pet."""
Information that's passed to a function is called an print(f"\nI have a {animal}.")
musician = build_person('janis', 'joplin')
argument; information that's received by a function is called print(f"Its name is {name}.")
print(musician)
a parameter. Arguments are included in parentheses after
the function's name, and parameters are listed in describe_pet('harry', 'hamster')
parentheses in the function's definition. describe_pet('willie') Visualizing functions
Try running some of these examples on pythontutor.com.
Passing a single argument Using None to make an argument optional
def greet_user(username): def describe_pet(animal, name=None):
"""Display a simple greeting."""
print(f"Hello, {username}!")
"""Display information about a pet."""
print(f"\nI have a {animal}.")
Python Crash Course
if name: A Hands-On, Project-Based
greet_user('jesse') print(f"Its name is {name}.") Introduction to Programming
greet_user('diana')
greet_user('brandon') describe_pet('hamster', 'harry')
nostarch.com/pythoncrashcourse2e
describe_pet('snake')
Passing a list to a function Passing an arbitrary number of arguments Modules
You can pass a list as an argument to a function, and the Sometimes you won't know how many arguments a You can store your functions in a separate file called a
function can work with the values in the list. Any changes function will need to accept. Python allows you to collect an module, and then import the functions you need into the file
the function makes to the list will affect the original list. You arbitrary number of arguments into one parameter using the containing your main program. This allows for cleaner
can prevent a function from modifying a list by passing a * operator. A parameter that accepts an arbitrary number of program files. (Make sure your module is stored in the
copy of the list as an argument. arguments must come last in the function definition. same directory as your main program.)
The ** operator allows a parameter to collect an arbitrary
Passing a list as an argument number of keyword arguments. These arguments are Storing a function in a module
File: pizza.py
def greet_users(names): stored as a dictionary with the parameter names as keys,
"""Print a simple greeting to everyone.""" and the arguments as values. def make_pizza(size, *toppings):
for name in names: """Make a pizza."""
Collecting an arbitrary number of arguments print(f"\nMaking a {size} pizza.")
msg = f"Hello, {name}!"
print(msg) def make_pizza(size, *toppings): print("Toppings:")
"""Make a pizza.""" for topping in toppings:
usernames = ['hannah', 'ty', 'margot'] print(f"\nMaking a {size} pizza.") print(f"- {topping}")
greet_users(usernames) print("Toppings:")
for topping in toppings: Importing an entire module
Allowing a function to modify a list File: making_pizzas.py
print(f"- {topping}") Every function in the module is available in the program file.
The following example sends a list of models to a function for
printing. The original list is emptied, and the second list is filled. import pizza
# Make three pizzas with different toppings.
def print_models(unprinted, printed): make_pizza('small', 'pepperoni')
"""3d print a set of models.""" make_pizza('large', 'bacon bits', 'pineapple') pizza.make_pizza('medium', 'pepperoni')
while unprinted: make_pizza('medium', 'mushrooms', 'peppers', pizza.make_pizza('small', 'bacon', 'pineapple')
current_model = unprinted.pop() 'onions', 'extra cheese')
Importing a specific function
print(f"Printing {current_model}")
Collecting an arbitrary number of keyword arguments Only the imported functions are available in the program file.
printed.append(current_model)
def build_profile(first, last, **user_info): from pizza import make_pizza
# Store some unprinted designs, """Build a dictionary for a user."""
# and print each of them. user_info['first'] = first make_pizza('medium', 'pepperoni')
unprinted = ['phone case', 'pendant', 'ring'] user_info['last'] = last make_pizza('small', 'bacon', 'pineapple')
printed = []
print_models(unprinted, printed) Giving a module an alias
return user_info
import pizza as p
print(f"\nUnprinted: {unprinted}") # Create two users with different kinds
print(f"Printed: {printed}") # of information. p.make_pizza('medium', 'pepperoni')
user_0 = build_profile('albert', 'einstein', p.make_pizza('small', 'bacon', 'pineapple')
Preventing a function from modifying a list
The following example is the same as the previous one, except the
location='princeton')
Giving a function an alias
original list is unchanged after calling print_models().
user_1 = build_profile('marie', 'curie', from pizza import make_pizza as mp
def print_models(unprinted, printed): location='paris', field='chemistry')
"""3d print a set of models.""" mp('medium', 'pepperoni')
while unprinted: print(user_0) mp('small', 'bacon', 'pineapple')
current_model = unprinted.pop() print(user_1)
print(f"Printing {current_model}") Importing all functions from a module
printed.append(current_model) Don't do this, but recognize it when you see it in others' code. It
can result in naming conflicts, which can cause errors.
# Store some unprinted designs,
What's the best way to structure a function?
from pizza import *
# and print each of them. As you can see there are many ways to write and call a
original = ['phone case', 'pendant', 'ring'] function. When you're starting out, aim for something that
make_pizza('medium', 'pepperoni')
printed = [] simply works. As you gain experience you'll develop an
understanding of the more subtle advantages of different make_pizza('small', 'bacon', 'pineapple')
print_models(original[:], printed) structures such as positional and keyword arguments, and
print(f"\nOriginal: {original}") the various approaches to importing functions. For now if More cheat sheets available at
print(f"Printed: {printed}") your functions do what you need them to, you're doing well.
ehmatthes.github.io/pcc_2e/
Beginner's Python
Creating and using a class (cont.) Class inheritance
If the class you're writing is a specialized version of another
Creating an object from a class class, you can use inheritance. When one class inherits

Cheat Sheet - Classes my_car = Car('audi', 'a4', 2016)


Accessing attribute values
from another, it automatically takes on all the attributes and
methods of the parent class. The child class is free to
introduce new attributes and methods, and override
attributes and methods of the parent class.
print(my_car.make)
To inherit from another class include the name of the
What are classes? print(my_car.model)
parent class in parentheses when defining the new class.
print(my_car.year)
Classes are the foundation of object-oriented The __init__() method for a child class
Calling methods
programming. Classes represent real-world things
class ElectricCar(Car):
you want to model in your programs: for example my_car.fill_tank()
"""A simple model of an electric car."""
dogs, cars, and robots. You use a class to make my_car.drive()
objects, which are specific instances of dogs, cars, Creating multiple objects def __init__(self, make, model, year):
and robots. A class defines the general behavior that """Initialize an electric car."""
a whole category of objects can have, and the my_car = Car('audi', 'a4', 2019) super().__init__(make, model, year)
information that can be associated with those objects. my_old_car = Car('subaru', 'outback', 2015)
my_truck = Car('toyota', 'tacoma', 2012)
Classes can inherit from each other – you can # Attributes specific to electric cars.
write a class that extends the functionality of an # Battery capacity in kWh.
existing class. This allows you to code efficiently for a Modifying attributes self.battery_size = 75
wide variety of situations. # Charge level in %.
You can modify an attribute's value directly, or you can
self.charge_level = 0
write methods that manage updating values more carefully.
Creating and using a class Modifying an attribute directly Adding new methods to the child class
Consider how we might model a car. What information class ElectricCar(Car):
my_new_car = Car('audi', 'a4', 2019)
would we associate with a car, and what behavior would it --snip--
my_new_car.fuel_level = 5
have? The information is stored in variables called def charge(self):
attributes, and the behavior is represented by functions. Writing a method to update an attribute's value """Fully charge the vehicle."""
Functions that are part of a class are called methods. self.charge_level = 100
def update_fuel_level(self, new_level): print("The vehicle is fully charged.")
The Car class """Update the fuel level."""
class Car:
if new_level <= self.fuel_capacity: Using child methods and parent methods
self.fuel_level = new_level
"""A simple attempt to model a car.""" my_ecar = ElectricCar('tesla', 'model s', 2019)
else:
print("The tank can't hold that much!")
def __init__(self, make, model, year): my_ecar.charge()
"""Initialize car attributes.""" Writing a method to increment an attribute's value my_ecar.drive()
self.make = make
self.model = model def add_fuel(self, amount):
self.year = year """Add fuel to the tank."""
if (self.fuel_level + amount Finding your workflow
# Fuel capacity and level in gallons. <= self.fuel_capacity): There are many ways to model real world objects and
self.fuel_capacity = 15 self.fuel_level += amount situations in code, and sometimes that variety can feel
self.fuel_level = 0 print("Added fuel.") overwhelming. Pick an approach and try it – if your first
else: attempt doesn't work, try a different approach.
def fill_tank(self): print("The tank won't hold that much.")
"""Fill gas tank to capacity."""
self.fuel_level = self.fuel_capacity
print("Fuel tank is full.") Naming conventions
Python Crash Course
In Python class names are written in CamelCase and object
A Hands-On, Project-Based
def drive(self): names are written in lowercase with underscores. Modules Introduction to Programming
"""Simulate driving.""" that contain classes should be named in lowercase with
print("The car is moving.") underscores. nostarch.com/pythoncrashcourse2e
Class inheritance (cont.) Importing classes Understanding self
Class files can get long as you add detailed information and People often ask what the self variable represents. The
Overriding parent methods functionality. To help keep your program files uncluttered, self variable is a reference to an object that's been
class ElectricCar(Car): you can store your classes in modules and import the created from the class.
--snip-- classes you need into your main program. The self variable provides a way to make other variables
def fill_tank(self): and objects available everywhere in a class. The self
Storing classes in a file
"""Display an error message.""" car.py
variable is automatically passed to each method that's
print("This car has no fuel tank!") called through an object, which is why you see it listed first
"""Represent gas and electric cars.""" in every method definition. Any variable attached to self is
available everywhere in the class.
Instances as attributes class Car:
A class can have objects as attributes. This allows classes """A simple attempt to model a car.""" Understanding __init__()
to work together to model complex situations. --snip—
The __init__() method is a function that's part of a class,
A Battery class class Battery: just like any other method. The only special thing about
"""A battery for an electric car.""" __init__() is that it's called automatically every time you
class Battery: make a new object from a class. If you accidentally misspell
"""A battery for an electric car.""" --snip--
__init__(), the method will not be called and your object
class ElectricCar(Car): may not be created correctly.
def __init__(self, size=75):
"""Initialize battery attributes.""" """A simple model of an electric car."""
# Capacity in kWh, charge level in %. --snip-- Storing objects in a list
self.size = size Importing individual classes from a module A list can hold as many items as you want, so you can
self.charge_level = 0 my_cars.py make a large number of objects from a class and store
them in a list.
def get_range(self): from car import Car, ElectricCar Here's an example showing how to make a fleet of rental
"""Return the battery's range.""" cars, and make sure all the cars are ready to drive.
if self.size == 75: my_beetle = Car('volkswagen', 'beetle', 2016)
my_beetle.fill_tank() A fleet of rental cars
return 260
elif self.size == 100: my_beetle.drive() from car import Car, ElectricCar
return 315
my_tesla = ElectricCar('tesla', 'model s', # Make lists to hold a fleet of cars.
Using an instance as an attribute 2016) gas_fleet = []
my_tesla.charge() electric_fleet = []
class ElectricCar(Car):
my_tesla.drive()
--snip--
Importing an entire module # Make 500 gas cars and 250 electric cars.
def __init__(self, make, model, year): for _ in range(500):
"""Initialize an electric car.""" import car car = Car('ford', 'escape', 2019)
super().__init__(make, model, year) gas_fleet.append(car)
my_beetle = car.Car( for _ in range(250):
# Attribute specific to electric cars. 'volkswagen', 'beetle', 2019) ecar = ElectricCar('nissan', 'leaf', 2019)
self.battery = Battery() my_beetle.fill_tank() electric_fleet.append(ecar)
my_beetle.drive()
def charge(self): # Fill the gas cars, and charge electric cars.
"""Fully charge the vehicle.""" my_tesla = car.ElectricCar( for car in gas_fleet:
self.battery.charge_level = 100 'tesla', 'model s', 2019) car.fill_tank()
print("The vehicle is fully charged.") my_tesla.charge() for ecar in electric_fleet:
my_tesla.drive() ecar.charge()
Using the instance
Importing all classes from a module
my_ecar = ElectricCar('tesla', 'model x', 2019) (Don’t do this, but recognize it when you see it.)
print(f"Gas cars: {len(gas_fleet)}")
print(f"Electric cars: {len(electric_fleet)}")
from car import *
my_ecar.charge()
print(my_ecar.battery.get_range())
my_beetle = Car('volkswagen', 'beetle', 2016) More cheat sheets available at
my_ecar.drive()
ehmatthes.github.io/pcc_2e/
Beginner's Python
Reading from a file (cont.) File paths (cont.)
Storing the lines in a list Opening a file using an absolute path

Cheat Sheet – filename = 'siddhartha.txt' f_path = "/home/ehmatthes/books/alice.txt"

Files and Exceptions


with open(filename) as f_obj: with open(f_path) as f:
lines = f_obj.readlines() lines = f.readlines()

for line in lines: Opening a file on Windows


Windows will sometimes interpret forward slashes incorrectly. If
print(line.rstrip())
you run into this, use backslashes in your file paths.
What are files? What are exceptions? f_path = "C:\Users\ehmatthes\books\alice.txt"
Writing to a file
Your programs can read information in from files, and Passing the 'w' argument to open() tells Python you want
they can write data to files. Reading from files allows with open(f_path) as f:
to write to the file. Be careful; this will erase the contents of lines = f.readlines()
you to work with a wide variety of information; writing the file if it already exists. Passing the 'a' argument tells
to files allows users to pick up where they left off the Python you want to append to the end of an existing file.
next time they run your program. You can write text to The try-except block
files, and you can store Python structures such as Writing to an empty file When you think an error may occur, you can write a try-
lists in data files. filename = 'programming.txt' except block to handle the exception that might be raised.
The try block tells Python to try running some code, and
the except block tells Python what to do if the code results
Exceptions are special objects that help your with open(filename, 'w') as f:
f.write("I love programming!") in a particular kind of error.
programs respond to errors in appropriate ways. For
example if your program tries to open a file that Writing multiple lines to an empty file Handling the ZeroDivisionError exception
doesn’t exist, you can use exceptions to display an
filename = 'programming.txt' try:
informative error message instead of having the print(5/0)
program crash. except ZeroDivisionError:
with open(filename, 'w') as f:
f.write("I love programming!\n") print("You can't divide by zero!")
Reading from a file f.write("I love creating new games.\n") Handling the FileNotFoundError exception
To read from a file your program needs to open the file and
Appending to a file f_name = 'siddhartha.txt'
then read the contents of the file. You can read the entire
contents of the file at once, or read the file line by line. The filename = 'programming.txt'
with statement makes sure the file is closed properly when try:
the program has finished accessing the file. with open(filename, 'a') as f: with open(f_name) as f:
f.write("I also love working with data.\n") lines = f.readlines()
Reading an entire file at once f.write("I love making apps as well.\n") except FileNotFoundError:
filename = 'siddhartha.txt' msg = f"Can’t find file: {f_name}."
print(msg)
File paths
with open(filename) as f_obj:
contents = f_obj.read() When Python runs the open() function, it looks for the file Knowing which exception to handle
in the same directory where the program that's being
executed is stored. You can open a file from a subfolder It can be hard to know what kind of exception to handle
print(contents) when writing code. Try writing your code without a try
using a relative path. You can also use an absolute path to
Reading line by line open any file on your system. block, and make it generate an error. The traceback will tell
Each line that's read from the file has a newline character at the you what kind of exception your program needs to handle.
end of the line, and the print function adds its own newline Opening a file from a subfolder
character. The rstrip() method gets rid of the extra blank lines
this would result in when printing to the terminal.
f_path = "text_files/alice.txt"
Python Crash Course
filename = 'siddhartha.txt' with open(f_path) as f: A Hands-On, Project-Based
lines = f.readlines() Introduction to Programming
with open(filename) as f_obj:
for line in f_obj: for line in lines:
print(line.rstrip()) print(line.rstrip()) nostarch.com/pythoncrashcourse2e
The else block Failing silently Storing data with json
The try block should only contain code that may cause an Sometimes you want your program to just continue running The json module allows you to dump simple Python data
error. Any code that depends on the try block running when it encounters an error, without reporting the error to structures into a file, and load the data from that file the
successfully should be placed in the else block. the user. Using the pass statement in an else block allows next time the program runs. The JSON data format is not
you to do this. specific to Python, so you can share this kind of data with
Using an else block people who work in other languages as well.
Using the pass statement in an else block
print("Enter two numbers. I'll divide them.")
f_names = ['alice.txt', 'siddhartha.txt', Knowing how to manage exceptions is important when
x = input("First number: ") 'moby_dick.txt', 'little_women.txt'] working with stored data. You'll usually want to make sure
y = input("Second number: ") the data you're trying to load exists before working with it.
for f_name in f_names: Using json.dump() to store data
try: # Report the length of each file found.
result = int(x) / int(y) try: """Store some numbers."""
except ZeroDivisionError: with open(f_name) as f:
print("You can't divide by zero!") lines = f.readlines() import json
else: except FileNotFoundError:
print(result) # Just move on to the next file. numbers = [2, 3, 5, 7, 11, 13]
pass
Preventing crashes from user input else: filename = 'numbers.json'
Without the except block in the following example, the program with open(filename, 'w') as f:
num_lines = len(lines)
would crash if the user tries to divide by zero. As written, it will
msg = f"{f_name} has {num_lines}" json.dump(numbers, f)
handle the error gracefully and keep running.
msg += " lines."
"""A simple calculator for division only.""" print(msg)
Using json.load() to read data
"""Load some previously stored numbers."""
print("Enter two numbers. I'll divide them.")
print("Enter 'q' to quit.")
Avoid bare except blocks
import json
Exception-handling code should catch specific exceptions
while True: that you expect to happen during your program's execution.
filename = 'numbers.json'
x = input("\nFirst number: ") A bare except block will catch all exceptions, including
with open(filename) as f:
if x == 'q': keyboard interrupts and system exits you might need when
numbers = json.load(f)
break forcing a program to close.
y = input("Second number: ") print(numbers)
if y == 'q': If you want to use a try block and you're not sure which
break exception to catch, use Exception. It will catch most Making sure the stored data exists
exceptions, but still allow you to interrupt programs
intentionally. import json
try:
result = int(x) / int(y) Don’t use bare except blocks f_name = 'numbers.json'
except ZeroDivisionError:
print("You can't divide by zero!") try:
try:
else: # Do something
with open(f_name) as f:
print(result) except:
numbers = json.load(f)
pass
except FileNotFoundError:
Deciding which errors to report Use Exception instead msg = f"Can’t find file: {f_name}."
Well-written, properly tested code is not very prone to print(msg)
try: else:
internal errors such as syntax or logical errors. But every
# Do something print(numbers)
time your program depends on something external such as
except Exception:
user input or the existence of a file, there's a possibility of
pass
an exception being raised. Practice with exceptions
Printing the exception Take a program you've already written that prompts for user
It's up to you how to communicate errors to your users. input, and add some error-handling code to the program.
Sometimes users need to know if a file is missing; try:
sometimes it's better to handle the error silently. A little # Do something
experience will help you know how much to report. except Exception as e: More cheat sheets available at
print(e, type(e)) ehmatthes.github.io/pcc_2e/
Beginner's Python
Testing a function (cont.) A failing test (cont.)
Building a testcase with one unit test Running the test

Cheat Sheet –
To build a test case, make a class that inherits from When you change your code, it’s important to run your existing
unittest.TestCase and write methods that begin with test_. tests. This will tell you whether the changes you made affected
Save this as test_full_names.py existing behavior.

Testing Your Code import unittest


from full_names import get_full_name
E
================================================
ERROR: test_first_last (__main__.NamesTestCase)
class NamesTestCase(unittest.TestCase): Test names like Janis Joplin.
"""Tests for names.py.""" ------------------------------------------------
Why test your code? Traceback (most recent call last):
def test_first_last(self): File "test_full_names.py", line 10,
When you write a function or a class, you can also """Test names like Janis Joplin.""" in test_first_last
write tests for that code. Testing proves that your full_name = get_full_name('janis', 'joplin')
code works as it's supposed to in the situations it's 'joplin') TypeError: get_full_name() missing 1 required
designed to handle, and also when people use your self.assertEqual(full_name, positional argument: 'last'
programs in unexpected ways. Writing tests gives 'Janis Joplin')
you confidence that your code will work correctly as ------------------------------------------------
more people begin to use your programs. You can if __name__ == '__main__': Ran 1 test in 0.001s
also add new features to your programs and know unittest.main()
that you haven't broken existing behavior. FAILED (errors=1)
Running the test
Python reports on each unit test in the test case. The dot reports a Fixing the code
A unit test verifies that one specific aspect of your single passing test. Python informs us that it ran 1 test in less than When a test fails, the code needs to be modified until the test
code works as it's supposed to. A test case is a 0.001 seconds, and the OK lets us know that all unit tests in the passes again. (Don’t make the mistake of rewriting your tests to fit
test case passed. your new code.) Here we can make the middle name optional.
collection of unit tests which verify your code's
behavior in a wide variety of situations. . def get_full_name(first, last, middle=''):
--------------------------------------- """Return a full name."""
Ran 1 test in 0.000s if middle:
Testing a function: A passing test full_name = f"{first} {middle} {last}"
Python's unittest module provides tools for testing your OK else:
code. To try it out, we’ll create a function that returns a full full_name = f"{first} {last}"
name. We’ll use the function in a regular program, and then
build a test case for the function.
Testing a function: A failing test
return full_name.title()
Failing tests are important; they tell you that a change in the
A function to test code has affected existing behavior. When a test fails, you Running the test
Save this as full_names.py need to modify the code so the existing behavior still works. Now the test should pass again, which means our original
def get_full_name(first, last): functionality is still intact.
Modifying the function
"""Return a full name.""" We’ll modify get_full_name() so it handles middle names, but .
full_name = f"{first} {last}" we’ll do it in a way that breaks existing behavior. ---------------------------------------
return full_name.title() Ran 1 test in 0.000s
def get_full_name(first, middle, last):
Using the function """Return a full name."""
OK
Save this as names.py full_name = f"{first} {middle} {last}"
return full_name.title()
from full_names import get_full_name
Using the function
janis = get_full_name('janis', 'joplin')
print(janis) from full_names import get_full_name
Python Crash Course
bob = get_full_name('bob', 'dylan') john = get_full_name('john', 'lee', 'hooker') A Hands-On, Project-Based
print(bob) print(john) Introduction to Programming
david = get_full_name('david', 'lee', 'roth')
print(david) nostarch.com/pythoncrashcourse2e
Adding new tests Testing a class The setUp() method
You can add as many unit tests to a test case as you need. Testing a class is similar to testing a function, since you’ll When testing a class, you usually have to make an instance
To write a new test, add a new method to your test case mostly be testing your methods. of the class. The setUp() method is run before every test.
class. Any instances you make in setUp() are available in every
A class to test test you write.
Testing middle names Save as accountant.py
We’ve shown that get_full_name() works for first and last
class Accountant(): Using setUp() to support multiple tests
names. Let’s test that it works for middle names as well. The instance self.acc can be used in each new test.
"""Manage a bank account."""
import unittest import unittest
from full_names import get_full_name def __init__(self, balance=0): from accountant import Accountant
self.balance = balance
class NamesTestCase(unittest.TestCase): class TestAccountant(unittest.TestCase):
"""Tests for names.py.""" def deposit(self, amount): """Tests for the class Accountant."""
self.balance += amount
def test_first_last(self): def setUp(self):
"""Test names like Janis Joplin.""" def withdraw(self, amount): self.acc = Accountant()
full_name = get_full_name('janis', self.balance -= amount
'joplin') def test_initial_balance(self):
self.assertEqual(full_name, Building a testcase # Default balance should be 0.
'Janis Joplin') For the first test, we’ll make sure we can start out with different
initial balances. Save this as test_accountant.py. self.assertEqual(self.acc.balance, 0)

def test_middle(self): import unittest # Test non-default balance.


"""Test names like David Lee Roth.""" from accountant import Accountant acc = Accountant(100)
full_name = get_full_name('david', self.assertEqual(acc.balance, 100)
'roth', 'lee') class TestAccountant(unittest.TestCase):
self.assertEqual(full_name, """Tests for the class Accountant.""" def test_deposit(self):
'David Lee Roth') # Test single deposit.
def test_initial_balance(self): self.acc.deposit(100)
if __name__ == '__main__': # Default balance should be 0. self.assertEqual(self.acc.balance, 100)
unittest.main() acc = Accountant()
self.assertEqual(acc.balance, 0) # Test multiple deposits.
Running the tests
The two dots represent two passing tests.
self.acc.deposit(100)
# Test non-default balance. self.acc.deposit(100)
.. acc = Accountant(100) self.assertEqual(self.acc.balance, 300)
--------------------------------------- self.assertEqual(acc.balance, 100)
Ran 2 tests in 0.000s def test_withdrawal(self):
OK if __name__ == '__main__': # Test single withdrawal.
unittest.main() self.acc.deposit(1000)
A variety of assert methods Running the test
self.acc.withdraw(100)
self.assertEqual(self.acc.balance, 900)
Python provides a number of assert methods you can use
.
to test your code.
--------------------------------------- if __name__ == '__main__':
Verify that a == b, or a != b Ran 1 test in 0.000s unittest.main()
OK
assertEqual(a, b) Running the tests
assertNotEqual(a, b)
When is it okay to modify tests? ...
Verify that x is True, or x is False In general you shouldn’t modify a test once it’s written. ---------------------------------------
When a test fails it usually means new code you’ve written Ran 3 tests in 0.001s
assertTrue(x)
assertFalse(x) has broken existing functionality, and you need to modify
the new code until all existing tests pass. OK
Verify an item is in a list, or not in a list If your original requirements have changed, it may be
appropriate to modify some tests. This usually happens in
assertIn(item, list) the early stages of a project when desired behavior is still More cheat sheets available at
assertNotIn(item, list) being sorted out, and no one is using your code yet. ehmatthes.github.io/pcc_2e/
Beginner's Python Starting a game (cont.)
Setting a custom window size
Pygame rect objects (cont.)
Creating a rect object

Cheat Sheet - Pygame The display.set_mode() function accepts a tuple that defines
the screen size.
screen_dim = (1500, 1000)
You can create a rect object from scratch. For example a small rect
object that’s filled in can represent a bullet in a game. The Rect()
class takes the coordinates of the upper left corner, and the width
and height of the rect. The draw.rect() function takes a screen
self.screen = pg.display.set_mode(screen_dim) object, a color, and a rect. This function fills the given rect with the
What is Pygame? given color.
Setting a custom background color
Colors are defined as a tuple of red, green, and blue values. Each bullet_rect = pg.Rect(100, 100, 3, 15)
Pygame is a framework for making games using value ranges from 0-255. color = (100, 100, 100)
Python. Making games is fun, and it’s a great way to pg.draw.rect(screen, color, bullet_rect)
def __init__(self):
expand your programming skills and knowledge.
--snip--
Pygame takes care of many of the lower-level tasks
in building games, which lets you focus on the
self.bg_color = (225, 225, 225) Working with images
aspects of your game that make it interesting. Many objects in a game are images that are moved around
def run_game(self): the screen. It’s easiest to use bitmap (.bmp) image files, but
while True: you can also configure your system to work with jpg, png,
Installing Pygame for event in pg.event.get(): and gif files as well.
--snip--
Pygame runs on all systems, and you should be able to
Loading an image
install it in one line.
self.screen.fill(self.bg_color)
ship = pg.image.load('images/ship.bmp')
Installing Pygame pg.display.flip()
Getting the rect object from an image
$ python -m pip install --user pygame
ship_rect = ship.get_rect()
Pygame rect objects
Starting a game Many objects in a game can be treated as simple Positioning an image
The following code sets up an empty game window, and rectangles, rather than their actual shape. This simplifies With rects, it’s easy to position an image wherever you want on the
starts an event loop and a loop that continually refreshes screen, or in relation to another object. The following code
code without noticeably affecting game play. Pygame has a
positions a ship at the bottom center of the screen, by matching the
the screen. rect object that makes it easy to work with game objects. midbottom of the ship with the midbottom of the screen.
An empty game window Getting the screen rect object ship_rect.midbottom = screen_rect.midbottom
We already have a screen object; we can easily access the rect
import sys object associated with the screen. Drawing an image to the screen
import pygame as pg Once an image is loaded and positioned, you can draw it to the
self.screen_rect = self.screen.get_rect()
screen with the blit() method. The blit() method acts on the
class AlienInvasion: Finding the center of the screen screen object, and takes the image object and image rect as
Rect objects have a center attribute which stores the center point. arguments.
def __init__(self):
screen_center = self.screen_rect.center # Draw ship to screen.
pg.init()
screen.blit(ship, ship_rect)
self.screen = pg.display.set_mode(
Useful rect attributes
(1200, 800)) Once you have a rect object, there are a number of attributes that If Pygame doesn't work on macOS
pg.display.set_caption( are useful when positioning objects and detecting relative positions
"Alien Invasion") Some versions of Pygame don't work on macOS, and you'll
of objects. (You can find more attributes in the Pygame
just see an empty black game window. If this happens, try
documentation. The self variable has been left off for clarity.)
installing a development version of Pygame.
def run_game(self):
# Individual x and y values:
while True: $ python -m pip install pygame==2.0.0.dev3
screen_rect.left, screen_rect.right
for event in pg.event.get():
screen_rect.top, screen_rect.bottom
if event.type == pg.QUIT:
sys.exit()
screen_rect.centerx, screen_rect.centery
screen_rect.width, screen_rect.height Python Crash Course
pg.display.flip() A Hands-On, Project-Based
# Tuples
screen_rect.center
Introduction to Programming
if __name__ == '__main__':
screen_rect.size
ai = AlienInvasion() nostarch.com/pythoncrashcourse2e
ai.run_game()
Working with images (cont.) Responding to mouse events Pygame groups (cont.)
Pygame’s event loop registers an event any time the
The blitme() method mouse moves, or a mouse button is pressed or released. Removing an item from a group
Game objects such as ships are often written as classes. Then a It’s important to delete elements that will never appear again in the
blitme() method is usually defined, which draws the object to the Responding to the mouse button game, so you don’t waste memory and resources.
screen.
for event in pg.event.get(): bullets.remove(bullet)
def blitme(self): if event.type == pg.MOUSEBUTTONDOWN:
"""Draw ship at current location.""" ship.fire_bullet() Detecting collisions
self.screen.blit(self.image, self.rect)
You can detect when a single object collides with any
Finding the mouse position
The mouse position is returned as a tuple.
member of a group. You can also detect when any member
Responding to keyboard input of one group collides with a member of another group.
Pygame watches for events such as key presses and mouse_pos = pg.mouse.get_pos()
mouse actions. You can detect any event you care about in Collisions between a single object and a group
the event loop, and respond with any action that’s
Clicking a button The spritecollideany() function takes an object and a group,
You might want to know if the cursor is over an object such as a and returns True if the object overlaps with any member of the
appropriate for your game. button. The rect.collidepoint() method returns true when a group.
Responding to key presses point is inside a rect object.
if pg.sprite.spritecollideany(ship, aliens):
Pygame’s main event loop registers a KEYDOWN event any time a if button_rect.collidepoint(mouse_pos): ships_left -= 1
key is pressed. When this happens, you can check for specific start_game()
keys. Collisions between two groups
for event in pg.event.get(): Hiding the mouse The sprite.groupcollide() function takes two groups, and two
booleans. The function returns a dictionary containing information
if event.type == pg.KEYDOWN: pg.mouse.set_visible(False) about the members that have collided. The booleans tell Pygame
if event.key == pg.K_RIGHT: whether to delete the members of either group that have collided.
ship_rect.x += 1
elif event.key == pg.K_LEFT: Pygame groups collisions = pg.sprite.groupcollide(
ship_rect.x -= 1 Pygame has a Group class which makes working with a bullets, aliens, True, True)
elif event.key == pg.K_SPACE: group of similar objects easier. A group is like a list, with
ship.fire_bullet() some extra functionality that’s helpful when building games. score += len(collisions) * alien_point_value
elif event.key == pg.K_q: Making and filling a group
sys.exit() An object that will be placed in a group must inherit from Sprite.
Rendering text
You can use text for a variety of purposes in a game. For
Responding to released keys from pygame.sprite import Sprite, Group example you can share information with players, and you
When the user releases a key, a KEYUP event is triggered.
can display a score.
if event.type == pg.KEYUP: def Bullet(Sprite):
if event.key == pg.K_RIGHT: ... Displaying a message
def draw_bullet(self): The following code defines a message, then a color for the text and
ship.moving_right = False the background color for the message. A font is defined using the
...
default system font, with a font size of 48. The font.render()
def update(self): function is used to create an image of the message, and we get the
The game is an object ... rect object associated with the image. We then center the image
In the overall structure shown here (under Starting a on the screen and display it.
Game), the entire game is written as a class. This makes it bullets = Group()
possible to write programs that play the game msg = "Play again?"
automatically, and it also means you can build an arcade new_bullet = Bullet() msg_color = (100, 100, 100)
with a collection of games. bullets.add(new_bullet) bg_color = (230, 230, 230)

Pygame documentation Looping through the items in a group f = pg.font.SysFont(None, 48)


The sprites() method returns all the members of a group. msg_image = f.render(msg, True, msg_color,
The Pygame documentation is really helpful when building bg_color)
your own games. The home page for the Pygame project is for bullet in bullets.sprites():
msg_image_rect = msg_image.get_rect()
at http://pygame.org/, and the home page for the bullet.draw_bullet()
msg_image_rect.center = screen_rect.center
documentation is at http://pygame.org/docs/.
Calling update() on a group screen.blit(msg_image, msg_image_rect)
The most useful part of the documentation are the pages
Calling update() on a group automatically calls update() on
about specific parts of Pygame, such as the Rect() class each member of the group.
and the sprite module. You can find a list of these More cheat sheets available at
elements at the top of the help pages. bullets.update() ehmatthes.github.io/pcc_2e/
Beginner's Python
Customizing Plots Customizing plots (cont.)
Plots can be customized in a wide variety of ways. Just
about any element of a plot can be customized. Emphasizing points

Cheat Sheet –
You can plot as much data as you want on one plot. Here we re-
Using built-in styles plot the first and last points larger to emphasize them.
Matplotlib comes with a number of built-in styles, which you can
import matplotlib.pyplot as plt

Matplotlib
use with one additional line. The style must be specified before you
create the figure.
x_values = list(range(1000))
import matplotlib.pyplot as plt squares = [x**2 for x in x_values]

x_values = list(range(1000)) fig, ax = plt.subplots()


What is Matplotlib? squares = [x**2 for x in x_values] ax.scatter(x_values, squares, c=squares,
cmap=plt.cm.Blues, s=10)
Data visualization involves exploring data through plt.style.use('seaborn')
visual representations. The matplotlib package fig, ax = plt.subplots() ax.scatter(x_values[0], squares[0], c='green',
helps you make visually appealing representations of ax.scatter(x_values, squares, s=10) s=100)
the data you’re working with. Matplotlib is extremely plt.show() ax.scatter(x_values[-1], squares[-1], c='red',
flexible; these examples will help you get started with s=100)
Seeing available styles
a few simple visualizations. You can see all available styles on your system. This can be done
in a terminal session. ax.set_title('Square Numbers', fontsize=24)
--snip--
Installing Matplotlib >>> import matplotlib.pyplot as plt
Matplotlib runs on all systems, and you should be able to >>> plt.style.available Removing axes
install it in one line. ['seaborn-dark', 'seaborn-darkgrid', ... You can customize or remove axes entirely. Here’s how to access
each axis, and hide it.
Installing Matplotlib Adding titles and labels, and scaling axes
ax.get_xaxis().set_visible(False)
$ python -m pip install --user matplotlib import matplotlib.pyplot as plt ax.get_yaxis().set_visible(False)
Setting a custom figure size
Line graphs and scatter plots x_values = list(range(1000))
You can make your plot as big or small as you want by using the
squares = [x**2 for x in x_values] figsize argument. The dpi argument is optional; if you don’t
Making a line graph know your system’s resolution you can omit the argument and
fig represents the entire figure, or collection of plots; ax # Set overall style to use, and plot data. adjust the figsize argument accordingly.
represents a single plot in the figure. plt.style.use('seaborn')
fig, ax = plt.subplots() fig, ax = plt.subplots(figsize=(10, 6),
import matplotlib.pyplot as plt dpi=128)
ax.scatter(x_values, squares, s=10)
x_values = [0, 1, 2, 3, 4, 5] Saving a plot
squares = [0, 1, 4, 9, 16, 25] # Set chart title and label axes. The Matplotlib viewer has a save button, but you can also save
ax.set_title('Square Numbers', fontsize=24) your visualizations programmatically by replacing plt.show() with
ax.set_xlabel('Value', fontsize=14) plt.savefig().
fig, ax = plt.subplots()
ax.set_ylabel('Square of Value', fontsize=14)
ax.plot(x_values, squares) plt.savefig('squares.png', bbox_inches='tight')
# Set scale of axes, and size of tick labels.
plt.show()
ax.axis([0, 1100, 0, 1_100_000]) Online resources
Making a scatter plot ax.tick_params(axis='both', labelsize=14) The matplotlib gallery and documentation are at
scatter() takes a list of x and y values; the s=10 argument https://matplotlib.org/. Be sure to visit the examples, gallery,
controls the size of each point. plt.show() and pyplot links.
import matplotlib.pyplot as plt Using a colormap
x_values = list(range(1000))
A colormap varies the point colors from one shade to another,
based on a certain value for each point. The value used to
Python Crash Course
squares = [x**2 for x in x_values] determine the color of each point is passed to the c argument, and A Hands-On, Project-Based
the cmap argument specifies which colormap to use.
Introduction to Programming
fig, ax = plt.subplots() ax.scatter(x_values, squares, c=squares,
ax.scatter(x_values, squares, s=10) cmap=plt.cm.Blues, s=10) nostarch.com/pythoncrashcourse2e
plt.show()
Multiple plots Working with dates and times (cont.) Multiple plots in one figure
You can make as many plots as you want on one figure. You can include as many individual graphs in one figure as
When you make multiple plots, you can emphasize Datetime formatting arguments you want.
The strptime() function generates a datetime object from a
relationships in the data. For example you can fill the space
between two sets of data.
string, and the strftime() method generates a formatted string Sharing an x-axis
from a datetime object. The following codes let you work with dates The following code plots a set of squares and a set of cubes on
Plotting two sets of data exactly as you need to. two separate graphs that share a common x-axis.
Here we use ax.scatter() twice to plot square numbers and The plt.subplots() function returns a figure object and a tuple
%A Weekday name, such as Monday
cubes on the same figure. of axes. Each set of axes corresponds to a separate plot in the
%B Month name, such as January figure. The first two arguments control the number of rows and
import matplotlib.pyplot as plt %m Month, as a number (01 to 12) columns generated in the figure.
%d Day of the month, as a number (01 to 31)
%Y Four-digit year, such as 2016 import matplotlib.pyplot as plt
x_values = list(range(11))
squares = [x**2 for x in x_values] %y Two-digit year, such as 16
%H Hour, in 24-hour format (00 to 23) x_values = list(range(11))
cubes = [x**3 for x in x_values]
%I Hour, in 12-hour format (01 to 12) squares = [x**2 for x in x_values]
%p AM or PM cubes = [x**3 for x in x_values]
plt.style.use('seaborn')
fig, ax = plt.subplots() %M Minutes (00 to 59)
%S Seconds (00 to 61) fig, axs = plt.subplots(2, 1, sharex=True)
ax.scatter(x_values, squares, c='blue', s=10)
Converting a string to a datetime object axs[0].scatter(x_values, squares)
ax.scatter(x_values, cubes, c='red', s=10)
axs[0].set_title('Squares')
new_years = dt.strptime('1/1/2019', '%m/%d/%Y')
plt.show()
Converting a datetime object to a string axs[1].scatter(x_values, cubes, c='red')
Filling the space between data sets axs[1].set_title('Cubes')
The fill_between() method fills the space between two data ny_string = new_years.strftime('%B %d, %Y')
sets. It takes a series of x-values and two series of y-values. It also print(ny_string) plt.show()
takes a facecolor to use for the fill, and an optional alpha
argument that controls the color’s transparency. Plotting high temperatures Sharing a y-axis
The following code creates a list of dates and a corresponding list To share a y-axis, we use the sharey=True argument.
ax.fill_between(x_values, cubes, squares, of high temperatures. It then plots the high temperatures, with the
facecolor='blue', alpha=0.25) date labels displayed in a specific format. import matplotlib.pyplot as plt
from datetime import datetime as dt
x_values = list(range(11))
Working with dates and times squares = [x**2 for x in x_values]
Many interesting data sets have a date or time as the x- import matplotlib.pyplot as plt
from matplotlib import dates as mdates cubes = [x**3 for x in x_values]
value. Python’s datetime module helps you work with this
kind of data. plt.style.use('seaborn')
dates = [
fig, axs = plt.subplots(1, 2, sharey=True)
Generating the current date dt(2019, 6, 21), dt(2019, 6, 22),
The datetime.now() function returns a datetime object dt(2019, 6, 23), dt(2019, 6, 24),
representing the current date and time. ] axs[0].scatter(x_values, squares)
axs[0].set_title('Squares')
from datetime import datetime as dt
highs = [56, 57, 57, 64]
axs[1].scatter(x_values, cubes, c='red')
today = dt.now() axs[1].set_title('Cubes')
date_string = today.strftime('%m/%d/%Y') fig, ax = plt.subplots()
print(date_string) ax.plot(dates, highs, c='red')
plt.show()
Generating a specific date ax.set_title("Daily High Temps", fontsize=24)
You can also generate a datetime object for any date and time you ax.set_ylabel("Temp (F)", fontsize=16)
want. The positional order of arguments is year, month, and day. x_axis = ax.get_xaxis()
The hour, minute, second, and microsecond arguments are x_axis.set_major_formatter(
optional.
mdates.DateFormatter('%B %d %Y')
from datetime import datetime as dt )
fig.autofmt_xdate()
new_years = dt(2019, 1, 1) More cheat sheets available at
fall_equinox = dt(year=2019, month=9, day=22) plt.show() ehmatthes.github.io/pcc_2e/
Beginner's Python
Line graphs, scatter plots, and bar graphs (cont.) Multiple plots
You can include as many data series as you want in a
Making a bar graph visualization. To do this, create one dictionary for each data

Cheat Sheet – Plotly


To make a bar graph, pass your data to the Bar() graph object.
series, and put these dictionaries in the data list. Each of
from plotly.graph_objs import Bar these dictionaries is referred to as a trace in the Plotly
--snip-- documentation.

data = [Bar(x=x_values, y=squares)] Plotting squares and cubes


What is Plotly? Here we use the 'name' attribute to set the label for each

# Pass the data and a filename to plot(). from plotly.graph_objs import Scatter
Data visualization involves exploring data through
offline.plot(data, filename='squares.html') from plotly import offline
visual representations. Plotly helps you make visually
appealing representations of the data you’re working
with. Plotly is particularly well suited for visualizations Adding a title and labels x_values = list(range(11))
squares = [x**2 for x in x_values]
that will be presented online, because it supports Using Layout objects cubes = [x**3 for x in x_values]
interactive elements. The Layout class allows you to specify titles, labels, and other
formatting directives for your visualizations. data = [
Installing Plotly from plotly.graph_objs import Scatter, Layout {
from plotly import offline # Trace 1: squares
Plotly runs on all systems, and can be installed in one line.
'type': 'scatter',
Installing Plotly x_values = list(range(11)) 'x': x_values,
squares = [x**2 for x in x_values] 'y': squares,
$ python -m pip install --user plotly 'name': 'Squares',
# Add a title, and a label for each axis. },
Line graphs, scatter plots, and bar graphs data = [Scatter(x=x_values, y=squares)] {
To make a plot with Plotly, you specify the data and then # Trace 2: cubes
pass it to a graph object. The data is stored in a list, so you title = 'Square Numbers' 'type': 'scatter',
can add as much data as you want to any graph. x_axis_config = {'title': 'x'} 'x': x_values,
In offline mode, the output should open automatically in a y_axis_config = {'title': 'Square of x'} 'y': cubes,
browser window. 'name': 'Cubes',
my_layout = Layout(title=title, },
Making a line graph ]
A line graph is a scatter plot where the points are connected. xaxis=x_axis_config, yaxis=y_axis_config)

from plotly.graph_objs import Scatter offline.plot( offline.plot(data,


from plotly import offline {'data': data, 'layout': my_layout}, filename='squares_cubes.html')
filename='squares.html')
# Define the data.
Online resources
x_values = list(range(11)) Specifying complex data
squares = [x**2 for x in x_values] The Plotly documentation is extensive and well-organized.
Start with the overview at https://plot.ly/python/. Here you
Data as a dictionary
# Pass the data to a graph object, and store it Plotly is highly customizable, and most of that flexibility comes from
can see an example of all the basic chart types, and click
# in a list. representing data and formatting directives as a dictionary. Here is on any example to see a relevant tutorial.
the same data from the previous examples, defined as a dictionary. Then take a look at the Python Figure Reference, at
data = [Scatter(x=x_values, y=squares)]
Defining the data as a dictionary also allows you to specify more https://plot.ly/python/reference/. Make sure to click on the
information about each series. Anything that pertains to a specific "How are Plotly attributes organized?" section. It's short, but
# Pass the data and a filename to plot(). data series such as markers, lines, and point labels, goes in the really helpful.
offline.plot(data, filename='squares.html') data dictionary. Plotly has several ways of specifying data, but
internally all data is represented in this way.
Making a scatter plot
To make a scatter plot, use the mode='markers' argument to tell
Plotly to only display the markers.
data = [{ Python Crash Course
'type': 'scatter',
A Hands-On, Project-Based
data = [Scatter(x=x_values, y=squares, 'x': x_values,
'y': squares, Introduction to Programming
mode='markers')]
'mode': 'markers',
}] nostarch.com/pythoncrashcourse2e
Specifying complex layouts Specifying complex layouts (cont.) Plotting global datasets
You can also specify the layout of your visualization as a Plotly has a variety of mapping tools. For example, if you
dictionary, which gives you much more control of the overall Using a colorscale have a set of points represented by latitude and longitude,
Colorscales are often used to show variations in large datasets. In
layout. you can create a scatter plot of those points overlaying a
Plotly, colorscales are set in the marker dictionary, nested inside a
data dictionary.
map.
Layout as a dictionary
Here is the same layout we used earlier, written as a dictionary. data = [{ The scattergeo chart type
Simple elements such as the title of the chart are just key-value Here's a map showing the location of three of the higher peaks in
pairs. More complex elements such as axes, which can have many
'type': 'scatter',
North America. If you hover over each point, you'll see its location
of their own settings, are nested dictionaries. 'x': x_values, and the name of the mountain.
'y': squares,
my_layout = { 'mode': 'markers', from plotly import offline
'title': 'Square Numbers', 'marker': {
'xaxis': { 'colorscale': 'Viridis', # Points in (lat, lon) format.
'title': 'x', 'color': squares, peak_coords = [
}, 'colorbar': {'title': 'Value'}, (63.069, -151.0063),
'yaxis': { }, (60.5671, -140.4055),
'title': 'Square of x', }] (46.8529, -121.7604),
}, ]
}
Using Subplots # Make matching lists of lats, lons,
A more complex layout It's often useful to have multiple plots share the same axes. # and labels.
Here is a layout for the same data, with more specific formatting This is done using the subplots module.
directives in the data and layout dictionaries. lats = [pc[0] for pc in peak_coords]
Adding subplots to a figure lons = [pc[1] for pc in peak_coords]
from plotly.graph_objs import Scatter peak_names = ['Denali', 'Mt Logan',
To use the subplots module, you make a figure to hold all the
from plotly import offline charts that will be made. Then you use the add_trace() method 'Mt Rainier']
to add each data series to the overall figure.
x_values = list(range(11)) For more help, see the documentation at data = [{
squares = [x**2 for x in x_values] https://plot.ly/python/subplots/. 'type': 'scattergeo',
from plotly.subplots import make_subplots 'lon': lons,
data = [{ 'lat': lats,
from plotly.graph_objects import Scatter
'type': 'scatter', 'marker': {
from plotly import offline
'x': x_values, 'size': 20,
'y': squares, 'color': '#227722',
x_values = list(range(11))
'mode': 'markers', },
squares = [x**2 for x in x_values]
'marker': { 'text': peak_names,
cubes = [x**3 for x in x_values]
'size': 10, }]
'color': '#6688dd',
fig = make_subplots(rows=1, cols=2,
}, my_layout = {
shared_yaxes=True)
}] 'title': 'Selected High Peaks',
data = { 'geo': {
my_layout = { 'scope': 'north america',
'type': 'scatter',
'title': 'Square Numbers', 'showland': True,
'x': x_values,
'xaxis': { 'showocean': True,
'y': squares,
'title': 'x', 'showlakes': True,
}
'titlefont': {'family': 'monospace'}, 'showrivers': True,
fig.add_trace(data, row=1, col=1)
}, },
'yaxis': { }
data = {
'title': 'Square of x',
'type': 'scatter',
'titlefont': {'family': 'monospace'}, offline.plot(
'x': x_values,
}, {'data': data, 'layout': my_layout},
'y': cubes,
} filename='peaks.html')
}
fig.add_trace(data, row=1, col=2)
offline.plot(
{'data': data, 'layout': my_layout},
More cheat sheets available at
offline.plot(fig, filename='subplots.html') ehmatthes.github.io/pcc_2e/
filename='squares.html')
Beginner's Python
Working with models Building a simple home page
The data in a Django project is structured as a set of Users interact with a project through web pages, and a
models. project’s home page can start out as a simple page with no

Cheat Sheet – Django Defining a model


To define the models for your app, modify the file models.py that
was created in your app’s folder. The __str__() method tells
data. A page usually needs a URL, a view, and a template.
Mapping a project’s URLs
The project’s main urls.py file tells Django where to find the urls.py
Django how to represent data objects based on this model. files associated with each app in the project.
What is Django? from django.db import models from django.contrib import admin
from django.urls import path, include
Django is a web framework which helps you build class Topic(models.Model):
interactive websites using Python. With Django you """A topic the user is learning about.""" urlpatterns = [
define the kind of data your site needs to work with, path('admin/', admin.site.urls),
and you define the ways your users can work with text = models.CharField(max_length=200) path('', include('learning_logs.urls')),
that data. date_added = models.DateTimeField( ]
auto_now_add=True)
Mapping an app’s URLs
Installing Django An app’s urls.py file tells Django which view to use for each URL in
def __str__(self):
It’s usually best to install Django to a virtual environment, the app. You’ll need to make this file yourself, and save it in the
return self.text
where your project can be isolated from your other Python app’s folder.
projects. Most commands assume you’re working in an Activating a model from django.urls import path
active virtual environment. To use a model the app must be added to the list
INSTALLED_APPS, which is stored in the project’s settings.py file.
Create a virtual environment from . import views
INSTALLED_APPS = [
$ python –m venv ll_env # My apps. app_name = 'learning_logs'
Activate the environment (macOS and Linux) 'learning_logs', urlpatterns = [
# Home page.
$ source ll_env/bin/activate # Default Django apps. path('', views.index, name='index'),
'django.contrib.admin', ]
Activate the environment (Windows)
]
> ll_env\Scripts\activate Writing a simple view
Migrating the database A view takes information from a request and sends data to the
Install Django to the active environment The database needs to be modified to store the kind of data that browser, often through a template. View functions are stored in an
the model represents. You'll need to run these commands every app’s views.py file. This simple view function doesn’t pull in any
(ll_env)$ pip install Django time you create a new model, or modify an existing model. data, but it uses the template index.html to render the home page.

$ python manage.py makemigrations learning_logs from django.shortcuts import render


Creating a project $ python manage.py migrate
To start a project we’ll create a new project, create a def index(request):
Creating a superuser """The home page for Learning Log."""
database, and start a development server. A superuser is a user account that has access to all aspects of the return render(request,
Create a new project project. 'learning_logs/index.html')
$ django-admin startproject learning_log . $ python manage.py createsuperuser
Registering a model Online resources
Create a database
You can register your models with Django’s admin site, which The documentation for Django is available at
$ python manage.py migrate makes it easier to work with the data in your project. To do this, http://docs.djangoproject.com/. The Django documentation
modify the app’s admin.py file. View the admin site at is thorough and user-friendly, so check it out!
View the project http://localhost:8000/admin/.
After issuing this command, you can view the project at
http://localhost:8000/. from django.contrib import admin
Python Crash Course
$ python manage.py runserver from .models import Topic A Hands-On, Project-Based
Create a new app Introduction to Programming
A Django project is made up of one or more apps.
admin.site.register(Topic)

$ python manage.py startapp learning_logs nostarch.com/pythoncrashcourse2e


Building a simple home page (cont.) Another model Building a page with data (cont.)
A new model can use an existing model. The ForeignKey
Writing a simple template attribute establishes a connection between instances of the Using data in a template
A template sets up the structure for a page. It’s a mix of html and The data in the view function’s context dictionary is available
template code, which is like Python but not as powerful. Make a
two related models. Make sure to migrate the database
within the template. This data is accessed using template
folder called templates inside the project folder. Inside the after adding a new model to your app. variables, which are indicated by doubled curly braces.
templates folder make another folder with the same name as the The vertical line after a template variable indicates a filter. In this
app. This is where the template files should be saved.
Defining a model with a foreign key
case a filter called date formats date objects, and the filter
The home page template will be saved as class Entry(models.Model): linebreaks renders paragraphs properly on a web page.
learning_logs/templates/learning_logs/index.html. """Learning log entries for a topic.""" {% extends 'learning_logs/base.html' %}
<p>Learning Log</p> topic = models.ForeignKey(Topic,
on_delete=models.CASCADE) {% block content %}
<p>Learning Log helps you keep track of your text = models.TextField()
learning, for any topic you're learning date_added = models.DateTimeField( <p>Topic: {{ topic }}</p>
about.</p> auto_now_add=True)
<p>Entries:</p>
def __str__(self):
Template inheritance return f"{self.text[:50]}..."
<ul>
Many elements of a web page are repeated on every page {% for entry in entries %}
in the site, or every page in a section of the site. By writing <li>
one parent template for the site, and one for each section, Building a page with data <p>
you can easily modify the look and feel of your entire site. Most pages in a project need to present data that’s specific {{ entry.date_added|date:'M d, Y H:i' }}
to the current user. </p>
The parent template <p>
The parent template defines the elements common to a set of URL parameters {{ entry.text|linebreaks }}
pages, and defines blocks that will be filled by individual pages. A URL often needs to accept a parameter telling it which data to </p>
access from the database. The URL pattern shown here looks for
<p> the ID of a specific topic and assigns it to the parameter topic_id.
</li>
<a href="{% url 'learning_logs:index' %}"> {% empty %}
Learning Log urlpatterns = [ <li>There are no entries yet.</li>
</a> --snip-- {% endfor %}
</p> # Detail page for a single topic. </ul>
path('topics/<int:topic_id>/', views.topic,
{% block content %}{% endblock content %} name='topic'), {% endblock content %}
]
The child template
The child template uses the {% extends %} template tag to pull in Using data in a view
the structure of the parent template. It then defines the content for The view uses a parameter from the URL to pull the correct data The Django shell
any blocks defined in the parent template. from the database. In this example the view is sending a context You can explore the data in your project from the command
dictionary to the template, containing data that should be displayed line. This is helpful for developing queries and testing code
{% extends 'learning_logs/base.html' %} on the page. You'll need to import any model you're using. snippets.
{% block content %} def topic(request, topic_id): Start a shell session
"""Show a topic and all its entries."""
topic = Topic.objects.get(id=topic_id) $ python manage.py shell
<p>
entries = topic.entry_set.order_by(
Learning Log helps you keep track
'-date_added')
Access data from the project
of your learning, for any topic you're
learning about. context = { >>> from learning_logs.models import Topic
</p> 'topic': topic, >>> Topic.objects.all()
'entries': entries, [<Topic: Chess>, <Topic: Rock Climbing>]
{% endblock content %} } >>> topic = Topic.objects.get(id=1)
return render(request, >>> topic.text
'learning_logs/topic.html', context) 'Chess'
Template indentation
Python code is usually indented by four spaces. In Restarting the development server
templates you’ll often see two spaces used for indentation, If you make a change to your project and the change
because elements tend to be nested more deeply in More cheat sheets available at
doesn’t seem to have any effect, try restarting the server:
templates. $ python manage.py runserver ehmatthes.github.io/pcc_2e/
Beginner's Python
User accounts (cont.) User accounts (cont.)
Defining the URLs Showing the current login status

Cheat Sheet –
Users will need to be able to log in, log out, and register. Make a You can modify the base.html template to show whether the user is
new urls.py file in the users app folder. currently logged in, and to provide a link to the login and logout
pages. Django makes a user object available to every template,
from django.urls import path, include and this template takes advantage of this object.

Django, Part 2 from . import views


The user.is_authenticated tag allows you to serve specific
content to users depending on whether they have logged in or not.
The {{ user.username }} property allows you to greet users
app_name = 'users' who have logged in. Users who haven’t logged in see links to
urlpatterns = [ register or log in.

Users and forms # Include default auth urls. <p>


path('', include( <a href="{% url 'learning_logs:index' %}">
Most web applications need to let users create 'django.contrib.auth.urls')), Learning Log
accounts. This lets users create and work with their </a>
own data. Some of this data may be private, and # Registration page.
some may be public. Django’s forms allow users to path('register/', views.register, {% if user.is_authenticated %}
enter and modify their data. name='register'), Hello, {{ user.username }}.
] <a href="{% url 'users:logout' %}">
User accounts Log out
The login template
The login view is provided by default, but you need to provide your
</a>
User accounts are handled by a dedicated app called {% else %}
users. Users need to be able to register, log in, and log own login template. The template shown here displays a simple
login form, and provides basic error messages. Make a templates <a href="{% url 'users:register' %}">
out. Django automates much of this work for you. folder in the users folder, and then make a registration folder in the Register
Making a users app templates folder. Save this file as login.html. </a> -
The tag {% csrf_token %} helps prevent a common type of <a href="{% url 'users:login' %}">
After making the app, be sure to add 'users' to INSTALLED_APPS
attack with forms. The {{ form.as_p }} element displays the Log in
in the project’s settings.py file.
default login form in paragraph format. The <input> element
</a>
$ python manage.py startapp users named next redirects the user to the home page after a successful
login.
{% endif %}
Including URLS for the users app
Add a line to the project’s urls.py file so the users app’s URLs are {% extends "learning_logs/base.html" %} </p>
included in the project.
{% block content %} {% block content %}{% endblock content %}
from django.contrib import admin {% if form.errors %}
from django.urls import path, include <p> The logged_out template
Your username and password didn't match. The default logout view renders the page using the template
urlpatterns = [ logged_out.html, which needs to be saved in the
Please try again.
path('admin/', admin.site.urls), users/templates/registration folder.
</p>
path('users/', include('users.urls')), {% endif %} {% extends "learning_logs/base.html" %}
path('', include('learning_logs.urls')),
] <form method="post" {% block content %}
action="{% url 'users:login' %}"> <p>
You have been logged out. Thank you
Using forms in Django {% csrf token %} for visiting!
There are a number of ways to create forms and work with {{ form.as_p }} </p>
them. You can use Django’s defaults, or completely <button name="submit">Log in</button> {% endblock content %}
customize your forms. For a simple way to let users enter
data based on your models, use a ModelForm. This creates
Python Crash Course
<input type="hidden" name="next"
a form that allows users to enter data that will populate the value="{% url 'learning_logs:index' %}"/>
fields on a model.
The register view on the back of this sheet shows a simple A Hands-On, Project-Based
</form>
approach to form processing. If the view doesn’t receive Introduction to Programming
data from a form, it responds with a blank form. If it {% endblock content %}
receives POST data from a form, it validates the data and nostarch.com/pythoncrashcourse2e
then saves it to the database.
User accounts (cont.) User accounts (cont.) Connecting data to users (cont.)
The register view The register template Restricting access to logged-in users
The register view needs to display a blank registration form when The register.html template displays the registration form in Some pages are only relevant to registered users. The views for
the page is first requested, and then process completed paragraph formats. these pages can be protected by the @login_required decorator.
registration forms. A successful registration logs the user in and Any view with this decorator will automatically redirect non-logged
redirects to the home page. {% extends 'learning_logs/base.html' %} in users to an appropriate page. Here’s an example views.py file.
from django.shortcuts import render, redirect {% block content %} from django.contrib.auth.decorators import \
from django.contrib.auth import login login_required
from django.contrib.auth.forms import \ <form method='post' --snip--
UserCreationForm action="{% url 'users:register' %}">
@login_required
def register(request): {% csrf_token %} def topic(request, topic_id):
"""Register a new user.""" {{ form.as_p }} """Show a topic and all its entries."""

if request.method != 'POST': Setting the redirect URL


<button name='submit'>Register</button> The @login_required decorator sends unauthorized users to the
# Display blank registration form. <input type='hidden' name='next' login page. Add the following line to your project’s settings.py file
form = UserCreationForm() value="{% url 'learning_logs:index' %}"/> so Django will know how to find your login page.
else:
# Process completed form. </form> LOGIN_URL = 'users:login'
form = UserCreationForm(
data=request.POST)
Preventing inadvertent access
{% endblock content %} Some pages serve data based on a parameter in the URL. You
can check that the current user owns the requested data, and
if form.is_valid(): return a 404 error if they don’t. Here’s an example view.
new_user = form.save() Connecting data to users
Users will have data that belongs to them. Any model that should from django.http import Http404
# Log in, redirect to home page. be connected directly to a user needs a field connecting instances --snip--
login(request, new_user) of the model to a specific user.
return redirect( @login_required
Making a topic belong to a user def topic(request, topic_id):
'learning_logs:index') Only the highest-level data in a hierarchy needs to be directly
connected to a user. To do this import the User model, and add it """Show a topic and all its entries."""
# Display a blank or invalid form. as a foreign key on the data model. topic = Topics.objects.get(id=topic_id)
context = {'form': form} After modifying the model you’ll need to migrate the database. if topic.owner != request.user:
return render(request, You’ll need to choose a user ID to connect each existing instance raise Http404
to. --snip--
'registration/register.html', context)
from django.db import models
from django.contrib.auth.models import User Using a form to edit data
If you provide some initial data, Django generates a form
Styling your project class Topic(models.Model): with the user’s existing data. Users can then modify and
The django-bootstrap4 app allows you to use the Bootstrap """A topic the user is learning about.""" save their data.
library to make your project look visually appealing. The text = models.CharField(max_length=200)
app provides tags that you can use in your templates to date_added = models.DateTimeField( Creating a form with initial data
The instance parameter allows you to specify initial data for a form.
style individual elements on a page. Learn more at auto_now_add=True)
https://django-bootstrap4.readthedocs.io/. owner = models.ForeignKey(User, form = EntryForm(instance=entry)
on_delete=models.CASCADE)
Modifying data before saving
Deploying your project The argument commit=False allows you to make changes before
def __str__(self):
writing data to the database.
Heroku lets you push your project to a live server, making it return self.text
available to anyone with an internet connection. Heroku new_topic = form.save(commit=False)
Querying data for the current user
offers a free service level, which lets you learn the In a view, the request object has a user attribute. You can use this
new_topic.owner = request.user
deployment process without any commitment. You’ll need attribute to query for the user’s data. The filter() method then
new_topic.save()
to install a set of Heroku command line tools, and use git to pulls the data that belongs to the current user.
track the state of your project. See More cheat sheets available at
https://devcenter.heroku.com/, and click on the Python link. topics = Topic.objects.filter(
owner=request.user) ehmatthes.github.io/pcc_2e/

Das könnte Ihnen auch gefallen