python crash course

Getting Started

Setting up your Programming Environment

installing Python

https://www.python.org/downloads/

run the installer. Make sure you select the option Add Python to PATH, which will make it easier to configure your system correctly. Figure 1-1 shows this option selected.

Alt text

Running Python in a Terminal Session

Open a new command window and enter python in lowercase. You should
see a Python prompt (>>>), which means Windows has found the version of
Python you just installed.

Installing the Python Extension for VS Code

To install the Python extension, click the Manage icon, which looks
like a gear in the lower-left corner of the VS Code app. In the menu that
appears, click Extensions. Enter python in the search box and click the
Python extension. (If you see more than one extension named Python,
choose the one supplied by Microsoft.)

running hello_world.py

folder: python_work

file: hello_world.py

print("Hello Python world!")

vscode -> run -> Run Without Debugging or press CTRL-F5

Hello Python world!

Running Python Programs from a Terminal

terminal to run hello_world.py:

1
2
3
4
5
C:\> cd Desktop\python_work
C:\Desktop\python_work> dir
hello_world.py
C:\Desktop\python_work> python hello_world.py
Hello Python world!

First, use the cd command to navigate to the python_work folder, which is in the Desktop folder.

Next, use the dir command to make sure hello_world.py is in this folder.

Then run the file using the command python hello_world.py.

Variables and Simple Data Types

variable

1
2
message = "Hello Python world!"
print(message)

output

Hello Python world!

We’ve added a variable named message.

Every variable is connected to a
value, which is the information associated with that variable.


1
2
3
4
message = "Hello Python world!"
print(message)
message = "Hello Python Crash Course world!"
print(message)

output:

1
2
Hello Python world!
Hello Python Crash Course world!

You can change the value of a variable in your program at any time,
and Python will always keep track of its current value.

Naming and Using Variables

rules:

  • Variable names can contain only letters, numbers, and underscores.
    They can start with a letter or an underscore, but not with a number.
    For instance, you can call a variable message_1 but not 1_message.
  • Spaces are not allowed in variable names, but underscores can be used
    to separate words in variable names. For example, greeting_message works
    but greeting message will cause errors.
  • Avoid using Python keywords and function names as variable names.
    For example, do not use the word print as a variable name; Python
    has reserved it for a particular programmatic purpose. (See “Python
    Keywords and Built-in Functions” on page 466.)
  • Variable names should be short but descriptive. For example, name is
    better than n, student_name is better than s_n, and name_length is better
    than length_of_persons_name.
  • Be careful when using the lowercase letter l and the uppercase letter O
    because they could be confused with the numbers 1 and 0.

The Python variables you’re using at this point should be lowercase. You won’t get errors if you use uppercase letters, but uppercase letters in variable names have special meanings that we’ll discuss in later chapters.

Avoiding Name Errors When Using Variables

1
2
message = "Hello Python Crash Course reader!"
print(mesage)

When an error occurs in your program, The interpreter provides
a traceback when a program cannot run successfully.

A traceback is a record of where the interpreter ran into trouble when trying to execute your code.

example:

1
2
3
4
5
Traceback (most recent call last):
File "hello_world.py", line 2, in <module> # 1
print(mesage) # 2
^^^^^^
NameError: name 'mesage' is not defined. Did you mean: 'message'? # 3

The output reports that an error occurs in line 2 of the file hello_world.py and tells us what kind of error it found 3.
In this case it found a name error
and reports that the variable being printed, mesage, has not been defined.

A name error usually means we either forgot to set a variable’s value before using it, or we made a spelling mistake when entering the variable’s name.

If Python finds a variable name that’s similar to the one it doesn’t recognize, it will ask if that’s the name you meant to use.

Variables Are Labels

It’s much better to think of variables as labels that you can assign to values. You can
also say that a variable references a certain value.

Strings

A string is a series of characters.
Anything inside quotes is considered a string in Python, and you can use single or double quotes around your

strings like this:

“This is a string.”
‘This is also a string.’

use quotes and apostrophes within your strings:

‘I told my friend, “Python is my favorite language!”‘
“The language ‘Python’ is named after Monty Python, not the snake.”
“One of Python’s strengths is its diverse and supportive community.”

Changing Case in a String with Methods

string.title()

Return a version of the string where each word is titlecased.
More specifically, words start with uppercased characters and all remaining cased characters have lower case.

1
2
name = "ada lovelace"
print(name.title())

output:
Ada Lovelace

A method is an action that Python can perform on a piece of data. The dot (.) after name in name.title() tells Python to make the title() method act on the variable name.

Every method is followed by a set of parentheses, because
methods often need additional information to do their work. That information is provided inside the parentheses.

The title() function doesn’t need
any additional information, so its parentheses are empty.


change a string to all uppercase or all lowercase letters like this:

1
2
3
name = "Ada Lovelace"
print(name.upper())
print(name.lower())

This will display the following:

ADA LOVELACE
ada lovelace

The lower() method is particularly useful for storing data. You typically won’t want to trust the capitalization that your users provide, so you’ll convert strings to lowercase before storing them. Then when you want to display the information, you’ll use the case that makes the most sense foreach string.

Using Variables in Strings

use a variable’s value inside a string:

1
2
3
4
first_name = "ada"
last_name = "lovelace"
full_name = f"{first_name} {last_name}" # 1
print(full_name)

place the letter f immediately
before the opening quotation mark 1. Put braces around the name or
names of any variable you want to use inside the string.

These strings are called f-strings. The f is for format, because Python
formats the string by replacing the name of any variable in braces with its
value. The output from the previous code is:
ada lovelace


another example:

1
2
3
4
first_name = "ada"
last_name = "lovelace"
full_name = f"{first_name} {last_name}"
print(f"Hello, {full_name.title()}!") # 1

output:

Hello, Ada Lovelace!

Adding Whitespace to Strings with Tabs or Newlines

whitespace refers to any nonprinting characters, such as
spaces, tabs, and end-of-line symbols.
use whitespace to organize your output so it’s easier for users to read.

a tab \t:

1
2
3
4
>>> print("Python")
Python
>>> print("\tPython")
Python

newline \n:

1
2
3
4
5
>>> print("Languages:\nPython\nC\nJavaScript")
Languages:
Python
C
JavaScript

combine tabs and newlines:

1
2
3
4
5
>>> print("Languages:\n\tPython\n\tC\n\tJavaScript")
Languages:
Python
C
JavaScript

Stripping Whitespace

‘python’ and ‘python ‘ to a program, they are two different strings.

often you’ll want to compare two strings to determine whether they are the same. Extra whitespace can be confusing in much simpler situations as well.

eliminate extra whitespace from data that people enter.


To ensure that no whitespace exists at the right side of a string, use
the rstrip() method:

1
2
3
4
5
6
7
>>> favorite_language = 'python ' # 1
>>> favorite_language # 2
'python '
>>> favorite_language.rstrip() # 3
'python'
>>> favorite_language # 4
'python '

However, it is only removed temporarily. If you ask for the value
of favorite_language again, the string looks the same as when it was entered,
including the extra whitespace 4.
To remove the whitespace from the string permanently, you have to
associate the stripped value with the variable name:

1
2
3
4
>>> favorite_language = 'python '
>>> favorite_language = favorite_language.rstrip() # 1
>>> favorite_language
'python'

strip whitespace from the left side of a string using the lstrip() method
from both sides at once using strip():

1
2
3
4
5
6
7
>>> favorite_language = ' python '  # 1 
>>> favorite_language.rstrip() # 2
' python'
>>> favorite_language.lstrip() # 3
'python '
>>> favorite_language.strip() # 4
'python'

In the real world, these stripping functions are used most often to clean up
user input before it’s stored in a program.

Removing Prefixes

remove a prefix.

1
2
3
>>> nostarch_url = 'https://nostarch.com'
>>> nostarch_url.removeprefix('https://')
'nostarch.com'

Enter the name of the variable followed by a dot, and then the method
removeprefix(). Inside the parentheses, enter the prefix you want to remove
from the original string.

Like the methods for removing whitespace, removeprefix() leaves the
original string unchanged. If you want to keep the new value with the prefix removed, either reassign it to the original variable or assign it to a new
variable:

>>> simple_url = nostarch_url.removeprefix('https://')

Avoiding Syntax Errors with Strings

A syntax error occurs when Python doesn’t recognize a section of your program as valid Python code.

example

1
2
message = 'One of Python's strengths is its diverse community.'
print(message)

You’ll see the following output:

1
2
3
4
File "apostrophe.py", line 1
message = 'One of Python's strengths is its diverse community.'
1 ^
SyntaxError: unterminated string literal (detected at line 1)

Your editor’s syntax highlighting feature should help you spot some syntax errors quickly as you write your programs. If you see Python code highlighted as if it’s English or English highlighted as if it’s Python code, you probably have a mismatched quotation mark somewhere in your file.

Numbers

Integers

You can add (+), subtract (-), multiply (*), and divide (/) integers in Python.

1
2
3
4
5
6
7
8
>>> 2 + 3
5
>>> 3 - 2
1
>>> 2 * 3
6
>>> 3 / 2
1.5

uses two multiplication symbols to represent exponents:

1
2
3
4
5
6
>>> 3 ** 2
9
>>> 3 ** 3
27
>>> 10 ** 6
1000000

Python supports the order of operations too, so you can use multiple
operations in one expression. You can also use parentheses to modify the
order of operations. For example:

1
2
3
4
>>> 2 + 3*4
14
>>> (2 + 3) * 4
20

The spacing in these examples has no effect on how Python evaluates the expressions; it simply helps you more quickly spot the operations that have priority when you’re reading through the code.

Floats

Python calls any number with a decimal point a float. it refers to the fact that a decimal point Variables and can appear at any position in a number.

For the most part, you can use floats without worrying about how they
behave. Simply enter the numbers you want to use, and Python will most
likely do what you expect:

1
2
3
4
5
6
7
8
>>> 0.1 + 0.1
0.2
>>> 0.2 + 0.2
0.4
>>> 2 *0.1
0.2
>>> 2* 0.2
0.4

However, be aware that you can sometimes get an arbitrary number of
decimal places in your answer:

1
2
3
4
>>> 0.2 + 0.1
0.30000000000000004
>>> 3 * 0.1
0.30000000000000004

This happens in all languages and is of little concern. Python tries to
find a way to represent the result as precisely as possible, which is sometimes
difficult given how computers have to represent numbers internally.

Integers and Floats

When you divide any two numbers, even if they are integers that result in a
whole number, you’ll always get a float:

1
2
>>> 4/2
2.0

If you mix an integer and a float in any other operation, you’ll get a
float as well:

1
2
3
4
5
6
>>> 1 + 2.0
3.0
>>> 2 * 3.0
6.0
>>> 3.0 ** 2
9.0

Python defaults to a float in any operation that uses a float, even if the
output is a whole number.

Underscores in Numbers

When you’re writing long numbers, you can group digits using underscores
to make large numbers more readable:

1
2
3
>>> universe_age = 14_000_000_000
>>> print(universe_age)
14000000000

Python ignores the underscores when storing these kinds of values.

Even if you don’t group the digits in threes, the value will still be unaffected. To Python, 1000 is the same as 1_000, which is the same as 10_00. This
feature works for both integers and floats.

Multiple Assignment

You can assign values to more than one variable using just a single line of
code. This can help shorten your programs and make them easier to read;

you’ll use this technique most often when initializing a set of numbers.
For example, here’s how you can initialize the variables x, y, and z to zero:

>>> x, y, z = 0, 0, 0

You need to separate the variable names with commas, and do the same
with the values, and Python will assign each value to its respective variable.
As long as the number of values matches the number of variables, Python
will match them up correctly

Constants

A constant is a variable whose value stays the same throughout the life of a
program.

Python doesn’t have built-in constant types, but Python programmers use all capital letters to indicate a variable should be treated as a constant and never be changed:

MAX_CONNECTIONS = 5000

Comments

u should add notes within your programs that describe your overall approach to the
problem you’re solving.

A comment allows you to write notes in your spoken
language, within your programs.

How Do You Write Comments?

In Python, the hash mark (#) indicates a comment. Anything following a
hash mark in your code is ignored by the Python interpreter. For example:

1
2
# Say hello to everyone.
print("Hello Python people!")

Python ignores the first line and executes the second line.
Hello Python people!

Introducing Lists

what is a list

A list is a collection of items in a particular order

Because a list usually contains more than one element, it’s a good idea to make the name of your list plural, such as letters, digits, or names

In Python, square brackets ([]) indicate a list, and individual elements in the list are separated by commas.example

1
2
bicycles = ['trek', 'cannondale', 'redline', 'specialized']
print(bicycles)

output:
['trek', 'cannondale', 'redline', 'specialized']

Accessing Elements in a List

Lists are ordered collections, so you can access any element in a list by
telling Python the position, or index, of the item desired. To access an element in a list, write the name of the list followed by the index of the item
enclosed in square brackets.

1
2
bicycles = ['trek', 'cannondale', 'redline', 'specialized']
print(bicycles[0])

output
trek

Index Positions Start at 0, Not 1

Python has a special syntax for accessing the last element in a list. If you
ask for the item at index -1, Python always returns the last item in the list:

1
2
3
bicy
cles = ['trek', 'cannondale', 'redline', 'specialized']
print(bicycles[-1])

The index -2 returns the second item from the end of the list, the index -3 returns the third item from the end, and so forth.

Using Individual Values from a List

You can use individual values from a list just as you would any other variable.

1
2
3
bicycles = ['trek', 'cannondale', 'redline', 'specialized']
message = f"My first bicycle was a {bicycles[0].title()}."
print(message)

Modifying, Adding, and Removing Elements

Most lists you create will be dynamic, meaning you’ll build a list and then
add and remove elements from it as your program runs its course.

Modifying Elements in a List

To change an element, use the name of the list followed
by the index of the element you want to change, and then provide the new
value you want that item to have.

1
2
3
4
motorcycles = ['honda', 'yamaha', 'suzuki']
print(motorcycles)
motorcycles[0] = 'ducati'
print(motorcycles)

output
[‘honda’, ‘yamaha’, ‘suzuki’]
[‘ducati’, ‘yamaha’, ‘suzuki’]

Adding Elements to a List

Appending Elements to the End of a List

append the item to the
list. When you append an item to a list, the new element is added to the end
of the list

1
2
3
4
motorcycles = ['honda', 'yamaha', 'suzuki']
print(motorcycles)
motorcycles.append('ducati')
print(motorcycles)

To put your users in control, start by defining an empty list that
will hold the users’ values. Then append each new value provided to the list
you just created.

For example,

1
2
3
4
5
motorcycles = []
motorcycles.append('honda')
motorcycles.append('yamaha')
motorcycles.append('suzuki')
print(motorcycles)

output
[‘honda’, ‘yamaha’, ‘suzuki’]

Inserting Elements into a List

You can add a new element at any position in your list by using the insert()
method. You do this by specifying the index of the new element and the
value of the new item:
This operation shifts every other value in the list one position to the
right.

1
2
3
motorcycles = ['honda', 'yamaha', 'suzuki']
motorcycles.insert(0, 'ducati')
print(motorcycles)

output
[ducati’, ‘honda’, ‘yamaha’, ‘suzuki’]

Removing Elements from a List

Removing an Item Using the del Statement

know the position of the item you want to remove from a list, you can
use the del statement:

motorcycles = [‘honda’, ‘yamaha’, ‘suzuki’]
print(motorcycles)
del motorcycles[0]
print(motorcycles)

Removing an Item Using the pop() Method

The pop() method removes the last item in a list, but it lets you work
with that item after removing it. The term pop comes from thinking of a
list as a stack of items and popping one item off the top of the stack. In this
analogy, the top of a stack corresponds to the end of a list.

1
2
3
4
5
motorcycles = ['honda', 'yamaha', 'suzuki']
print(motorcycles)
popped_motorcycle = motorcycles.pop()
print(motorcycles)
print(popped_motorcycle)

[‘honda’, ‘yamaha’, ‘suzuki’]
[‘honda’, ‘yamaha’]
suzuki

Popping Items from Any Position in a List
1
2
3
motorcycles = ['honda', 'yamaha', 'suzuki']
first_owned = motorcycles.pop(0)
print(f"The first motorcycle I owned was a {first_owned.title()}.")

The first motorcycle I owned was a Honda.

Remember that each time you use pop(), the item you work with is no
longer stored in the list.

when you want to delete an item from a list and not use that item in any way, use the del statement; if you want to use an item as you remove it, use the pop() method.

Removing an Item by Value

If you only know the value of the item you want to remove, you
can use the remove() method

1
2
3
4
motorcycles = ['honda', 'yamaha', 'suzuki', 'ducati']
print(motorcycles)
motorcycles.remove('ducati')
print(motorcycles)

[‘honda’, ‘yamaha’, ‘suzuki’, ‘ducati’]
[‘honda’, ‘yamaha’, ‘suzuki’]

The remove() method deletes only the first occurrence of the value you specify. If there’s a possibility the value appears more than once in the list, you’ll need to use a loop to make sure all occurrences of the value are removed.

Organizing a List

Sometimes you’ll want
to preserve the original order of your list, and other times you’ll want to
change the original order.

Sorting a List Permanently with the sort() Method

The sort() method changes the order of the list permanently. The cars
are now in alphabetical order, and we can never revert to the original order:

1
2
3
cars = ['bmw', 'audi', 'toyota', 'subaru']
cars.sort()
print(cars)

[‘audi’, ‘bmw’, ‘subaru’, ‘toyota’]

o sort this list in reverse-alphabetical order

1
2
3
cars = ['bmw', 'audi', 'toyota', 'subaru']
cars.sort(reverse=True)
print(cars)

[‘toyota’, ‘subaru’, ‘bmw’, ‘audi’]

Sorting a List Temporarily with the sorted() Function

The sorted() function lets you display your list
in a particular order, but doesn’t affect the actual order of the list.

1
2
3
4
5
6
7
cars = ['bmw', 'audi', 'toyota', 'subaru']
print("Here is the original list:")
print(cars)
print("\nHere is the sorted list:")
print(sorted(cars))
print("\nHere is the original list again:")
print(cars)

output:

Here is the original list:
[‘bmw’, ‘audi’, ‘toyota’, ‘subaru’]
Here is the sorted list:
[‘audi’, ‘bmw’, ‘subaru’, ‘toyota’]
1 Here is the original list again:
[‘bmw’, ‘audi’, ‘toyota’, ‘subaru’]

The sorted() function can also accept a reverse=True
argument if you want to display a list in reverse-alphabetical order.

Sorting a list alphabetically is a bit more complicated when all the values are not in lowercase

Printing a List in Reverse Order

If we originally stored the list of cars in chronological order according to when
we owned them, we could easily rearrange the list into reverse-chronological
order:

1
2
3
4
cars = ['bmw', 'audi', 'toyota', 'subaru']
print(cars)
cars.reverse()
print(cars)

[‘bmw’, ‘audi’, ‘toyota’, ‘subaru’]
[‘subaru’, ‘toyota’, ‘audi’, ‘bmw’]

Finding the Length of a List

cars = [‘bmw’, ‘audi’, ‘toyota’, ‘subaru’]
len(cars)

Avoiding Index Errors When Working with Lists

1
2
motorcycles = ['honda', 'yamaha', 'suzuki']
print(motorcycles[3])

This example results in an index error:

1
2
3
4
5
Traceback (most recent call last):
File "motorcycles.py", line 2, in <module>
print(motorcycles[3])
~~~~~~~~~~~^^^
IndexError: list index out of range

Keep in mind that whenever you want to access the last item in a list,
you should use the index -1. This will always work, even if your list has
changed size since the last time you accessed it:

motorcycles = [‘honda’, ‘yamaha’, ‘suzuki’]
print(motorcycles[-1])

output:

suzuki


The only time this approach will cause an error is when you request the
last item from an empty list:

1
2
motorcycles = []
print(motorcycles[-1])

No items are in motorcycles, so Python returns another index error:

1
2
3
4
5
6
Traceback (most recent call last):
File "motorcyles.py", line 3, in <module>
print(motorcycles[-1])
~~~~~~~~~~~^^^^
IndexError: list index out of range

If an index error occurs and you can’t figure out how to resolve it, try
printing your list or just printing the length of your list. Your list might look
much different than you thought it did, especially if it has been managed
dynamically by your program. Seeing the actual list, or the exact number of
items in your list, can help you sort out such logical errors.

Working with Lists

Looping allows you to take the same action, or set
of actions, with every item in a list

Looping Through an Entire List

Say we have a list of magicians’ names, and we want to print out each name in the list.

We could do this by retrieving each name from the list individually, but this approach could cause several problems. For one, it would
be repetitive to do this with a long list of names. Also, we’d have to change
our code each time the list’s length changed. Using a for loop avoids both of
these issues by letting Python manage these issues internally.

1
2
3
magicians = ['alice', 'david', 'carolina']
for magician in magicians:
print(magician)

alice
david
carolina

A Closer Look at Looping

for magician in magicians:

This line tells Python to retrieve the first value from the list magicians and associate it with the variable magician.

the set of steps is repeated once for each item in the list, no matter how many items
are in the list.

you can choose
any name you want for the temporary variable that will be associated with
each value in the list. However, it’s helpful to choose a meaningful name
that represents a single item from the list.

Using singular and plural names can help
you identify whether a section of code is working with a single element from
the list or the entire list.

Doing More Work Within a for Loop

1
2
3
4
magicians = ['alice', 'david', 'carolina']
for magician in magicians:
print(f"{magician.title()}, that was a great trick!")
print(f"I can't wait to see your next trick, {magician.title()}.\n")

Alice, that was a great trick!
I can’t wait to see your next trick, Alice.

David, that was a great trick!
I can’t wait to see your next trick, David.

Carolina, that was a great trick!
I can’t wait to see your next trick, Carolina.

Doing Something After a for Loop

Any lines of code after the for loop that are not indented are executed
once without repetition.

1
2
3
4
5
magicians = ['alice', 'david', 'carolina']
for magician in magicians:
print(f"{magician.title()}, that was a great trick!")
print(f"I can't wait to see your next trick, {magician.title()}.\n")
print("Thank you, everyone. That was a great magic show!")

Alice, that was a great trick!
I can’t wait to see your next trick, Alice.

David, that was a great trick!
Working with Lists 53
I can’t wait to see your next trick, David.

Carolina, that was a great trick!
I can’t wait to see your next trick, Carolina.

Thank you, everyone. That was a great magic show!

Avoiding Indentation Errors

Python uses indentation to determine how a line, or group of lines, is related
to the rest of the program.

common indentation errors. For example, people
sometimes indent lines of code that don’t need to be indented or forget
to indent lines that need to be indented.

Forgetting to Indent

1
2
3
magicians = ['alice', 'david', 'carolina']
for magician in magicians:
print(magician)
1
2
3
4
File "magicians.py", line 3
print(magician)
^
IndentationError: expected an indented block after 'for' statement on line 2

Forgetting to Indent Additional Lines

This is a logical error. The syntax is valid Python code, but the code does
not produce the desired result because a problem occurs in its logic. If you
expect to see a certain action repeated once for each item in a list and it’s
executed only once, determine whether you need to simply indent a line or
a group of lines.

1
2
3
4
magicians = ['alice', 'david', 'carolina']
for magician in magicians:
print(f"{magician.title()}, that was a great trick!")
print(f"I can't wait to see your next trick, {magician.title()}.\n")

output:

Alice, that was a great trick!
David, that was a great trick!
Carolina, that was a great trick!
I can’t wait to see your next trick, Carolina.

Indenting Unnecessarily

1
2
message = "Hello Python world!"
print(message)

File “hello_world.py”, line 2
print(message)
^
IndentationError: unexpected indent

You can avoid unexpected indentation errors by indenting only when you have a specific reason to do so.

Indenting Unnecessarily After the Loop

1
2
3
4
5
magicians = ['alice', 'david', 'carolina']
for magician in magicians:
print(f"{magician.title()}, that was a great trick!")
print(f"I can't wait to see your next trick, {magician.title()}.\n")
print("Thank you everyone, that was a great magic show!")
1
2
3
4
5
6
7
8
9
10
11
12
Alice, that was a great trick!
I can't wait to see your next trick, Alice.

Thank you everyone, that was a great magic show!
David, that was a great trick!
I can't wait to see your next trick, David.

Thank you everyone, that was a great magic show!
Carolina, that was a great trick!
I can't wait to see your next trick, Carolina.

Thank you everyone, that was a great magic show!

This is another logical error, similar to the one in “Forgetting to Indent
Additional Lines” on page 54. Because Python doesn’t know what you’re
trying to accomplish with your code, it will run all code that is written in
valid syntax. If an action is repeated many times when it should be executed
only once, you probably need to unindent the code for that action.

Forgetting the Colon

1
2
3
magicians = ['alice', 'david', 'carolina']
for magician in magicians
print(magician)
1
2
3
4
 File "magicians.py", line 2
for magician in magicians
^
SyntaxError: expected ':'

Making Numerical Lists

Using the range() Function

range(stop) -> range object range(start, stop[, step]) -> range object

Return an object that produces a sequence of integers from start (inclusive) to stop (exclusive) by step. range(i, j) produces i, i+1, i+2, …, j-1. start defaults to 0, and stop is omitted! range(4) produces 0, 1, 2, 3. These are exactly the valid indices for a list of 4 elements. When step is given, it specifies the increment (or decrement).

generate a series of numbers.

1
2
for value in range(1, 5):
print(value)

output:
1
2
3
4

You can also pass range() only one argument, and it will start the
sequence of numbers at 0.

Using range() to Make a List of Numbers

convert the results of range()
directly into a list using the list() function.

1
2
numbers = list(range(1, 6))
print(numbers)

This is the result:
[1, 2, 3, 4, 5]


1
2
3
4
5
squares = []
for value in range(1, 11):
square = value ** 2
squares.append(square)
print(squares)

[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

Simple Statistics with a List of Numbers

1
2
3
4
5
6
7
>>> digits = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]
>>> min(digits)
0
>>> max(digits)
9
>>> sum(digits)
45

List Comprehensions

A list comprehension allows you to generate
this same list in just one line of code. A list comprehension combines the
for loop and the creation of new elements into one line, and automatically
appends each new element.

1
2
squares = [value**2 for value in range(1, 11)]
print(squares)

output:
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

Working with Part of a List

Slicing a List

To make a slice, you specify the index of the first and last elements you want
to work with.
n, Python stops one item before the
second index you specify.

1
2
players = ['charles', 'martina', 'michael', 'florence', 'eli']
print(players[0:3])

output:
[‘charles’, ‘martina’, ‘michael’]

1
2
players = ['charles', 'martina', 'michael', 'florence', 'eli']
print(players[:4])

[‘charles’, ‘martina’, ‘michael’, ‘florence’]

1
2
players = ['charles', 'martina', 'michael', 'florence', 'eli']
print(players[2:])

[‘michael’, ‘florence’, ‘eli’]

1
2
players = ['charles', 'martina', 'michael', 'florence', 'eli']
print(players[-3:])

Looping Through a Slice

1
2
3
4
players = ['charles', 'martina', 'michael', 'florence', 'eli']
print("Here are the first three players on my team:")
1 for player in players[:3]:
print(player.title())

Here are the first three players on my team:
Charles
Martina
Michael

Copying a List

1
2
3
4
5
6
7
8
my_foods = ['pizza', 'falafel', 'carrot cake']
friend_foods = my_foods[:]
my_foods.append('cannoli')
friend_foods.append('ice cream')
print("My favorite foods are:")
print(my_foods)
print("\nMy friend's favorite foods are:")
print(friend_foods)

My favorite foods are:
[‘pizza’, ‘falafel’, ‘carrot cake’, ‘cannoli’]
My friend’s favorite foods are:
[‘pizza’, ‘falafel’, ‘carrot cake’, ‘ice cream’]

1
2
3
4
5
6
7
8
9
my_foods = ['pizza', 'falafel', 'carrot cake']
# This doesn't work:
friend_foods = my_foods
my_foods.append('cannoli')
friend_foods.append('ice cream')
print("My favorite foods are:")
print(my_foods)
print("\nMy friend's favorite foods are:")
print(friend_foods)

My favorite foods are:
[‘pizza’, ‘falafel’, ‘carrot cake’, ‘cannoli’, ‘ice cream’]
My friend’s favorite foods are:
[‘pizza’, ‘falafel’, ‘carrot cake’, ‘cannoli’, ‘ice cream’]

Tuples

Lists work well for storing collections of items that can change throughout the
life of a program.

Python refers to values that cannot change as
immutable, and an immutable list is called a tuple.

Defining a Tuple

A tuple looks just like a list, except you use parentheses instead of square
brackets.

1
2
3
dimensions = (200, 50)
print(dimensions[0])
print(dimensions[1])

output
200
50


1
2
dimensions = (200, 50)
dimensions[0] = 250
1
2
3
4
Traceback (most recent call last):
File "dimensions.py", line 2, in <module>
dimensions[0] = 250
TypeError: 'tuple' object does not support item assignment

Tuples are technically defined by the presence of a comma; the parentheses make them
look neater and more readable. If you want to define a tuple with one element, you
need to include a trailing comma:
my_t = (3,)

Looping Through All Values in a Tuple

1
2
3
dimensions = (200, 50)
for dimension in dimensions:
print(dimension)

200
50

Writing Over a Tuple

Although you can’t modify a tuple, you can assign a new value to a variable
that represents a tuple

1
2
3
4
5
6
7
8
dimensions = (200, 50)
print("Original dimensions:")
for dimension in dimensions:
print(dimension)
dimensions = (400, 100)
print("\nModified dimensions:")
for dimension in dimensions:
print(dimension)

if Statements 0

Programming often involves examining
a set of conditions and deciding which
action to take based on those conditions.
Python’s if statement allows you to examine
the current state of a program and respond appropriately to that state.

a example

1
2
3
4
5
6
cars = ['audi', 'bmw', 'subaru', 'toyota']
for car in cars:
if car == 'bmw':
print(car.upper())
else:
print(car.title())

output

Audi
BMW
Subaru
Toyota

Conditional Tests

an expression that can be evaluated as
True or False and is called a conditional test. Python uses the values True and
False to decide whether the code in an if statement should be executed.

Checking for Equality

equality operator returns
True if the values on the left and right side of the operator match, and False if
they don’t match.

1
2
3
>>> car = 'audi'
>>> car == 'bmw'
False

Ignoring Case When Checking for Equality

1
2
3
4
5
6
7
>>> car = 'Audi'
>>> car == 'audi'
False
>>> car.lower() == 'audi'
True
>>> car
'Audi'

Checking for Inequality

1
2
3
requested_topping = 'mushrooms'
if requested_topping != 'anchovies':
print("Hold the anchovies!")

Hold the anchovies!

Numerical Comparisons

mathematical comparisons

1
2
3
4
5
6
7
8
9
>>> age = 19
>>> age < 21
True
>>> age <= 21
True
>>> age > 21
False
>>> age >= 21
False

Checking Multiple Conditions

Using and to Check Multiple Conditions

To check whether two conditions are both True simultaneously, use the keyword and to combine the two conditional tests; if each test passes, the overall
expression evaluates to True. If either test fails or if both tests fail, the expression evaluates to False.

1
2
3
4
5
6
7
>>> age_0 = 22
>>> age_1 = 18
>>> age_0 >= 21 and age_1 >= 21
False
>>> age_1 = 22
>>> age_0 >= 21 and age_1 >= 21
True

To improve readability, you can use parentheses around the individual
tests
(age_0 >= 21) and (age_1 >= 21)

Checking Whether a Value Is in a List

To find out whether a particular value is already in a list, use the keyword in.

1
2
3
4
5
>>> requested_toppings = ['mushrooms', 'onions', 'pineapple']
>>> 'mushrooms' in requested_toppings
True
>>> 'pepperoni' in requested_toppings
False

Checking Whether a Value Is Not in a List

1
2
3
4
banned_users = ['andrew', 'carolina', 'david']
user = 'marie'
if user not in banned_users:
print(f"{user.title()}, you can post a response if you wish.")

Marie, you can post a response if you wish.

Boolean Expressions

A Boolean expression is just another name for a conditional
test. A Boolean value is either True or False, just like the value of a conditional
expression after it has been evaluated.

if Statements

Simple if Statements

if conditional_test:
do something

if-else Statements

take one action when a conditional test passes and a different action in all other cases.
An if-else block is similar to a simple if statement, but the else statement allows
you to define an action or set of actions that are executed when the conditional test fails.

1
2
3
4
5
6
7
age = 17
if age >= 18:
print("You are old enough to vote!")
print("Have you registered to vote yet?")
else:
print("Sorry, you are too young to vote.")
print("Please register to vote as soon as you turn 18!")

Sorry, you are too young to vote.
Please register to vote as soon as you turn 18!

The if-elif-else Chain

Python’s if-elif-else syntax. Python executes only one
block in an if-elif-else chain. It runs each conditional test in order, until
one passes. When a test passes, the code following that test is executed and
Python skips the rest of the tests.

1
2
3
4
5
6
7
age = 12
if age < 4:
print("Your admission cost is $0.")
elif age < 18:
print("Your admission cost is $25.")
else:
print("Your admission cost is $40.")

Your admission cost is $25.

Using Multiple elif Blocks

1
2
3
4
5
6
7
8
9
10
age = 12
if age < 4:
price = 0
elif age < 18:
price = 25
elif age < 65:
price = 40
else:
price = 20
print(f"Your admission cost is ${price}.")

Omitting the else Block

Other times, it’s clearer to use an additional elif statement that catches the specific condition of interest

1
2
3
4
5
6
7
8
9
10
age = 12
if age < 4:
price = 0
elif age < 18:
price = 25
elif age < 65:
price = 40
elif age >= 65:
price = 20
print(f"Your admission cost is ${price}.")

The else block is a catchall statement. It matches any condition that
wasn’t matched by a specific if or elif test, and that can sometimes include
invalid or even malicious data.
If you have a specific final condition you’re
testing for, consider using a final elif block and omit the else block. As a
result, you’ll be more confident that your code will run only under the correct conditions.

Testing Multiple Conditions

The if-elif-else chain is powerful, but it’s only appropriate to use when you
just need one test to pass. As soon as Python finds one test that passes, it
skips the rest of the tests.

sometimes it’s important to check all conditions of interest. In
this case, you should use a series of simple if statements with no elif or else
blocks. This technique makes sense when more than one condition could
be True, and you want to act on every condition that is True.

1
2
3
4
5
6
7
8
requested_toppings = ['mushrooms', 'extra cheese']
if 'mushrooms' in requested_toppings:
print("Adding mushrooms.")
if 'pepperoni' in requested_toppings:
print("Adding pepperoni.")
if 'extra cheese' in requested_toppings:
print("Adding extra cheese.")
print("\nFinished making your pizza!")

Adding mushrooms.
Adding extra cheese.

Finished making your pizza!

wrong:

1
2
3
4
5
6
7
8
requested_toppings = ['mushrooms', 'extra cheese']
if 'mushrooms' in requested_toppings:
print("Adding mushrooms.")
elif 'pepperoni' in requested_toppings:
print("Adding pepperoni.")
elif 'extra cheese' in requested_toppings:
print("Adding extra cheese.")
print("\nFinished making your pizza!")

Adding mushrooms.

Finished making your pizza!

Using if Statements with Lists

Checking for Special Items

1
2
3
4
5
6
7
requested_toppings = ['mushrooms', 'green peppers', 'extra cheese']
for requested_topping in requested_toppings:
if requested_topping == 'green peppers':
print("Sorry, we are out of green peppers right now.")
else:
print(f"Adding {requested_topping}.")
print("\nFinished making your pizza!")

Adding mushrooms.
Sorry, we are out of green peppers right now.
Adding extra cheese.

Finished making your pizza!

Checking That a List Is Not Empty

we won’t be able to assume
that a list has any items in it each time a loop is run. In this situation, it’s
useful to check whether a list is empty before running a for loop.

1
2
3
4
5
6
7
requested_toppings = []
if requested_toppings:
for requested_topping in requested_toppings:
print(f"Adding {requested_topping}.")
print("\nFinished making your pizza!")
else:
print("Are you sure you want a plain pizza?")

Are you sure you want a plain pizza?

Using Multiple Lists

1
2
3
4
5
6
7
8
available_toppings = ['mushrooms', 'olives', 'green peppers', 'pepperoni', 'pineapple', 'extra cheese']
requested_toppings = ['mushrooms', 'french fries', 'extra cheese']
for requested_topping in requested_toppings:
if requested_topping in available_toppings:
print(f"Adding {requested_topping}.")
else:
print(f"Sorry, we don't have {requested_topping}.")
print("\nFinished making your pizza!")

Adding mushrooms.
Sorry, we don’t have french fries.
Adding extra cheese.

Finished making your pizza!

Dictionaries

A Simple Dictionary

1
2
3
alien_0 = {'color': 'green', 'points': 5}
print(alien_0['color'])
print(alien_0['points'])

green
5

Working with Dictionaries

A dictionary in Python is a collection of key-value pairs. Each key is connected to
a value, and you can use a key to access the value associated with that key. A
key’s value can be a number, a string, a list, or even another dictionary.

a dictionary is wrapped in braces ({}) with a series of key-value
pairs inside the braces

A key-value pair is a set of values associated with each other. When you
provide a key, Python returns the value associated with that key. Every key is
connected to its value by a colon, and individual key-value pairs are separated
by commas.

Accessing Values in a Dictionary

To get the value associated with a key, give the name of the dictionary and
then place the key inside a set of square brackets

Adding New Key-Value Pairs

To add a new key-value pair, you would give the
name of the dictionary followed by the new key in square brackets, along
with the new value.

1
2
3
4
5
alien_0 = {'color': 'green', 'points': 5}
print(alien_0)
alien_0['x_position'] = 0
alien_0['y_position'] = 25
print(alien_0)

{‘color’: ‘green’, ‘points’: 5}
{‘color’: ‘green’, ‘points’: 5, ‘x_position’: 0, ‘y_position’: 25}

Dictionaries retain the order in which they were defined

Starting with an Empty Dictionary

1
2
3
4
alien_0 = {}
alien_0['color'] = 'green'
alien_0['points'] = 5
print(alien_0)

{‘color’: ‘green’, ‘points’: 5}

Modifying Values in a Dictionary

To modify a value in a dictionary, give the name of the dictionary with the
key in square brackets and then the new value you want associated with
that key.

1
2
3
4
alien_0 = {'color': 'green'}
print(f"The alien is {alien_0['color']}.")
alien_0['color'] = 'yellow'
print(f"The alien is now {alien_0['color']}.")

The alien is green.
The alien is now yellow.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
alien_0 = {'x_position': 0, 'y_position': 25, 'speed': 'medium'}
print(f"Original position: {alien_0['x_position']}")
# Move the alien to the right.
# Determine how far to move the alien based on its current speed.
if alien_0['speed'] == 'slow':
x_increment = 1
elif alien_0['speed'] == 'medium':
x_increment = 2
else:
# This must be a fast alien.
x_increment = 3
# The new position is the old position plus the increment.
alien_0['x_position'] = alien_0['x_position'] + x_increment
print(f"New position: {alien_0['x_position']}")

Original x-position: 0
New x-position: 2

Removing Key-Value Pairs

1
2
3
4
alien_0 = {'color': 'green', 'points': 5}
print(alien_0)
del alien_0['points']
print(alien_0)

A Dictionary of Similar Objects

It’s good practice to include a comma after the
last key-value pair as well, so you’re ready to add a new key-value pair on the
next line.

1
2
3
4
5
6
7
8
favorite_languages = {
'jen': 'python',
'sarah': 'c',
'edward': 'rust',
'phil': 'python',
}
language = favorite_languages['sarah'].title()
print(f"Sarah's favorite language is {language}.")

Using get() to Access Values

1
2
alien_0 = {'color': 'green', 'speed': 'slow'}
print(alien_0['points'])
1
2
3
4
5
Traceback (most recent call last):
File "alien_no_points.py", line 2, in <module>
print(alien_0['points'])
~~~~~~~^^^^^^^^^^
KeyError: 'points'

As a second optional
argument, you can pass the value to be returned if the key doesn’t exist:

1
2
3
alien_0 = {'color': 'green', 'speed': 'slow'}
point_value = alien_0.get('points', 'No point value assigned.')
print(point_value)

No point value assigned.

If you leave out the second argument in the call to get() and the key doesn’t exist, Python will return the value None. The special value None means “no value exists.” This is not an error: it’s a special value meant to indicate the absence of a value.

Looping Through a Dictionary

Looping Through All Key-Value Pairs

1
2
3
4
5
6
7
8
9
user_0 = {
'username': 'efermi',
'first': 'enrico',
'last': 'fermi',
}

for key, value in user_0.items():
print(f"\nKey: {key}")
print(f"Value: {value}")

Key: username
Value: efermi
Key: first
Value: enrico
Key: last
Value: fermi

1
2
3
4
5
6
7
8
favorite_languages = {
'jen': 'python',
'sarah': 'c',
'edward': 'rust',
'phil': 'python',
}
for name, language in favorite_languages.items():
print(f"{name.title()}'s favorite language is {language.title()}.")

Jen’s favorite language is Python.
Sarah’s favorite language is C.
Edward’s favorite language is Rust.
Phil’s favorite language is Python.

Looping Through All the Keys in a Dictionary

1
2
3
4
5
6
7
8
favorite_languages = {
'jen': 'python',
'sarah': 'c',
'edward': 'rust',
'phil': 'python',
}
for name in favorite_languages.keys():
print(name.title())

Jen
Sarah
Edward
Phil

Looping through the keys is actually the default behavior when looping
through a dictionary, so this code would have exactly the same output if you
wrote:

for name in favorite_languages:

1
2
3
4
5
6
7
8
9
favorite_languages = {
--snip--
}
friends = ['phil', 'sarah']
for name in favorite_languages.keys():
print(f"Hi {name.title()}.")
if name in friends:
language = favorite_languages[name].title()
print(f"\t{name.title()}, I see you love {language}!")

Hi Jen.
Hi Sarah.
Sarah, I see you love C!
Hi Edward.
Hi Phil.
Phil, I see you love Python!

The keys() method isn’t just for looping: it actually returns a sequence of
all the keys

1
2
3
4
5
favorite_languages = {
--snip--
}
if 'erin' not in favorite_languages.keys():
print("Erin, please take our poll!")

Erin, please take our poll!

Looping Through a Dictionary’s Keys in a Particular Order

Looping through a dictionary returns the items in the same order they
were inserted.

1
2
3
4
5
6
7
8
favorite_languages = {
'jen': 'python',
'sarah': 'c',
'edward': 'rust',
'phil': 'python',
}
for name in sorted(favorite_languages.keys()):
print(f"{name.title()}, thank you for taking the poll.")

Edward, thank you for taking the poll.
Jen, thank you for taking the poll.
Phil, thank you for taking the poll.
Sarah, thank you for taking the poll.

Looping Through All Values in a Dictionary

use the values() method to return a sequence of values without any
keys

1
2
3
4
5
6
7
8
9
favorite_languages = {
'jen': 'python',
'sarah': 'c',
'edward': 'rust',
'phil': 'python',
}
print("The following languages have been mentioned:")
for language in favorite_languages.values():
print(language.title())

The following languages have been mentioned:
Python
C
Rust
Python

To see each language chosen without repetition, we can use a set. A set
is a collection in which each item must be unique:

1
2
3
4
5
6
favorite_languages = {
--snip--
}
print("The following languages have been mentioned:")
for language in set(favorite_languages.values()):
print(language.title())

The following languages have been mentioned:
Python
C
Rust

You can build a set directly using braces and separating the elements with commas:

languages = {‘python’, ‘rust’, ‘python’, ‘c’}
languages
{‘rust’, ‘python’, ‘c’}

Unlike
lists and dictionaries, sets do not retain items in any specific order.

Nesting

store multiple dictionaries in a list, or a list of
items as a value in a dictionary. This is called nesting. You can nest dictionaries inside a list, a list of items inside a dictionary, or even a dictionary inside
another dictionary.

1
2
3
4
5
6
alien_0 = {'color': 'green', 'points': 5}
alien_1 = {'color': 'yellow', 'points': 10}
alien_2 = {'color': 'red', 'points': 15}
aliens = [alien_0, alien_1, alien_2]
for alien in aliens:
print(alien)

{‘color’: ‘green’, ‘points’: 5}
{‘color’: ‘yellow’, ‘points’: 10}
{‘color’: ‘red’, ‘points’: 15}

1
2
3
4
5
6
7
8
9
10
11
12
# Make an empty list for storing aliens.
aliens = []
# Make 30 green aliens.
for alien_number in range(30):
new_alien = {'color': 'green', 'points': 5, 'speed': 'slow'}
aliens.append(new_alien)
# Show the first 5 aliens.
for alien in aliens[:5]:
print(alien)
print("...")
# Show how many aliens have been created.
print(f"Total number of aliens: {len(aliens)}")

{‘color’: ‘green’, ‘points’: 5, ‘speed’: ‘slow’}
{‘color’: ‘green’, ‘points’: 5, ‘speed’: ‘slow’}
{‘color’: ‘green’, ‘points’: 5, ‘speed’: ‘slow’}
{‘color’: ‘green’, ‘points’: 5, ‘speed’: ‘slow’}
{‘color’: ‘green’, ‘points’: 5, ‘speed’: ‘slow’}

Total number of aliens: 30

A List in a Dictionary

1
2
3
4
5
6
7
8
9
10
# Store information about a pizza being ordered.
pizza = {
'crust': 'thick',
'toppings': ['mushrooms', 'extra cheese'],
}
# Summarize the order.
print(f"You ordered a {pizza['crust']}-crust pizza "
"with the following toppings:")
for topping in pizza['toppings']:
print(f"\t{topping}")

You ordered a thick-crust pizza with the following toppings:
mushrooms
extra cheese

1
2
3
4
5
6
7
8
9
10
favorite_languages = {
'jen': ['python', 'rust'],
'sarah': ['c'],
'edward': ['rust', 'go'],
'phil': ['python', 'haskell'],
}
for name, languages in favorite_languages.items():
print(f"\n{name.title()}'s favorite languages are:")
for language in languages:
print(f"\t{language.title()}")

Jen’s favorite languages are:
Python
Rust
Sarah’s favorite languages are:
C
Edward’s favorite languages are:
Rust
Go
Phil’s favorite languages are:
Python
Haskell

A Dictionary in a Dictionary

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
users = {
'aeinstein': {
'first': 'albert',
'last': 'einstein',
'location': 'princeton',
},
'mcurie': {
'first': 'marie',
'last': 'curie',
'location': 'paris',
},
}
for username, user_info in users.items():
print(f"\nUsername: {username}")
full_name = f"{user_info['first']} {user_info['last']}"
location = user_info['location']
print(f"\tFull name: {full_name.title()}")
print(f"\tLocation: {location.title()}")

Username: aeinstein
Full name: Albert Einstein
Location: Princeton
Username: mcurie
Full name: Marie Curie
Location: Paris

Notice that the structure of each user’s dictionary is identical. Although
not required by Python, this structure makes nested dictionaries easier to
work with. If each user’s dictionary had different keys, the code inside the
for loop would be more complicated.

User Input and while Loops

How the input() Function Works

The input() function pauses your program and waits for the user to enter
some text. Once Python receives the user’s input, it assigns that input to a
variable to make it convenient for you to work with.

message = input(“Tell me something, and I will repeat it back to you: “)
print(message)

Writing Clear Prompts

include a clear, easy-tofollow prompt that tells the user exactly what kind of information you’re
looking for. Any statement that tells the user what to enter should work.

Add a space at the end of your prompts (after the colon in the preceding example) to separate the prompt from the user’s response and to make
it clear to your user where to enter their text.

1
2
name = input("Please enter your name: ")
print(f"\nHello, {name}!")

Please enter your name: Eric
Hello, Eric!

1
2
3
4
prompt = "If you share your name, we can personalize the messages you see."
prompt += "\nWhat is your first name? "
name = input(prompt)
print(f"\nHello, {name}!")

If you share your name, we can personalize the messages you see.
What is your first name? Eric
Hello, Eric!

Using int() to Accept Numerical Input

1
2
3
4
>>> age = input("How old are you? ")
How old are you? 21
>>> age
'21'
1
2
3
4
5
6
>>> age = input("How old are you? ")
How old are you? 21
>>> age >= 18
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: '>=' not supported between instances of 'str' and 'int'

age = input(“How old are you? “)
How old are you? 21
age = int(age)
age >= 18
True

The Modulo Operator

modulo operator (%),
which divides one number by another number and returns the remainder:

1
2
3
4
5
6
number = input("Enter a number, and I'll tell you if it's even or odd: ")
number = int(number)
if number % 2 == 0:
print(f"\nThe number {number} is even.")
else:
print(f"\nThe number {number} is odd.")

Introducing while Loops

1
2
3
4
current_number = 1
while current_number <= 5:
print(current_number)
current_number += 1

Letting the User Choose When to Quit

1
2
3
4
5
6
prompt = "\nTell me something, and I will repeat it back to you:"
prompt += "\nEnter 'quit' to end the program. "
message = ""
while message != 'quit':
message = input(prompt)
print(message)

Tell me something, and I will repeat it back to you:
Enter ‘quit’ to end the program. Hello everyone!
Hello everyone!
Tell me something, and I will repeat it back to you:
Enter ‘quit’ to end the program. Hello again.
Hello again.
Tell me something, and I will repeat it back to you:
Enter ‘quit’ to end the program. quit
quit

Using a Flag

more complicated programs in
which many different events could cause the program to stop running?
trying to test all these conditions in one while
statement becomes complicated and difficult.

For a program that should run only as long as many conditions are
true, you can define one variable that determines whether or not the entire
program is active. This variable, called a flag, acts as a signal to the program. We can write our programs so they run while the flag is set to True
and stop running when any of several events sets the value of the flag to
False.

1
2
3
4
5
6
7
8
9
prompt = "\nTell me something, and I will repeat it back to you:"
prompt += "\nEnter 'quit' to end the program. "
active = True
while active:
message = input(prompt)
if message == 'quit':
active = False
else:
print(message)

Using break to Exit a Loop

To exit a while loop immediately without running any remaining code in
the loop, regardless of the results of any conditional test, use the break statement.

1
2
3
4
5
6
7
8
prompt = "\nPlease enter the name of a city you have visited:"
prompt += "\n(Enter 'quit' when you are finished.) "
while True:
city = input(prompt)
if city == 'quit':
break
else:
print(f"I'd love to go to {city.title()}!")

Using continue in a Loop

Rather than breaking out of a loop entirely without executing the rest of its
code, you can use the continue statement to return to the beginning of the
loop, based on the result of a conditional test.

1
2
3
4
5
6
current_number = 0
while current_number < 10:
current_number += 1
if current_number % 2 == 0:
continue
print(current_number)

1
3
5
7
9

Avoiding Infinite Loops

1
2
3
4
# This loop runs forever!
x = 1
while x <= 5:
print(x)

If
your program gets stuck in an infinite loop, press CTRL-C or just close the
terminal window displaying your program’s output.

Using a while Loop with Lists and Dictionaries

A for loop is effective for looping through a list, but you shouldn’t modify a list inside a for loop because Python will have trouble keeping track of
the items in the list. To modify a list as you work through it, use a while loop

Moving Items from One List to Another

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# Start with users that need to be verified,
# and an empty list to hold confirmed users.
unconfirmed_users = ['alice', 'brian', 'candace']
confirmed_users = []
# Verify each user until there are no more unconfirmed users.
# Move each verified user into the list of confirmed users.
while unconfirmed_users:
current_user = unconfirmed_users.pop()
print(f"Verifying user: {current_user.title()}")
confirmed_users.append(current_user)
# Display all confirmed users.
print("\nThe following users have been confirmed:")
for confirmed_user in confirmed_users:
print(confirmed_user.title())

Verifying user: Candace
Verifying user: Brian
Verifying user: Alice

The following users have been confirmed:
Candace
Brian
Alice

Removing All Instances of Specific Values from a List

1
2
3
4
5
pets = ['dog', 'cat', 'dog', 'goldfish', 'cat', 'rabbit', 'cat']
print(pets)
while 'cat' in pets:
pets.remove('cat')
print(pets)

[‘dog’, ‘cat’, ‘dog’, ‘goldfish’, ‘cat’, ‘rabbit’, ‘cat’]
[‘dog’, ‘dog’, ‘goldfish’, ‘rabbit’]

Filling a Dictionary with User Input

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
responses = {}
# Set a flag to indicate that polling is active.
polling_active = True
while polling_active:
# Prompt for the person's name and response.
name = input("\nWhat is your name? ")
response = input("Which mountain would you like to climb someday? ")
# Store the response in the dictionary.
responses[name] = response
# Find out if anyone else is going to take the poll.
repeat = input("Would you like to let another person respond? (yes/ no) ")
if repeat == 'no':
polling_active = False
# Polling is complete. Show the results.
print("\n--- Poll Results ---")
for name, response in responses.items():
print(f"{name} would like to climb {response}.")

What is your name? Eric
Which mountain would you like to climb someday? Denali
Would you like to let another person respond? (yes/ no) yes
What is your name? Lynn
Which mountain would you like to climb someday? Devil’s Thumb
Would you like to let another person respond? (yes/ no) no
— Poll Results —
Eric would like to climb Denali.
Lynn would like to climb Devil’s Thumb.

Functions

Defining a Function

1
2
3
4
def greet_user():
"""Display a simple greeting."""
print("Hello!")
greet_user()

The text on the second line is a comment called a docstring, which
describes what the function does. When Python generates documentation
for the functions in your programs, it looks for a string immediately after
the function’s definition. These strings are usually enclosed in triple quotes,
which lets you write multiple lines.

Passing Information to a Function

1
2
3
4
def greet_user(username):
"""Display a simple greeting."""
print(f"Hello, {username.title()}!")
greet_user('jesse')

Hello, Jesse!

Arguments and Parameters

The variable username in the definition of greet_user() is an example of a
parameter, a piece of information the function needs to do its job. The value
‘jesse’ in greet_user(‘jesse’) is an example of an argument. An argument is
a piece of information that’s passed from a function call to a function.

Passing Arguments

Positional Arguments

def describe_pet(animal_type, pet_name):
“””Display information about a pet.”””
print(f”\nI have a {animal_type}.”)
print(f”My {animal_type}’s name is {pet_name.title()}.”)
describe_pet(‘hamster’, ‘harry’)

Multiple Function Calls

1
2
3
4
5
6
def describe_pet(animal_type, pet_name):
"""Display information about a pet."""
print(f"\nI have a {animal_type}.")
print(f"My {animal_type}'s name is {pet_name.title()}.")
describe_pet('hamster', 'harry')
describe_pet('dog', 'willie')

I have a hamster.
My hamster’s name is Harry.
I have a dog.
My dog’s name is Willie.

Order Matters in Positional Arguments
1
2
3
4
5
def describe_pet(animal_type, pet_name):
"""Display information about a pet."""
print(f"\nI have a {animal_type}.")
print(f"My {animal_type}'s name is {pet_name.title()}.")
describe_pet('harry', 'hamster')

I have a harry.
My harry’s name is Hamster.

Keyword Arguments

1
2
3
4
5
def describe_pet(animal_type, pet_name):
"""Display information about a pet."""
print(f"\nI have a {animal_type}.")
print(f"My {animal_type}'s name is {pet_name.title()}.")
describe_pet(animal_type='hamster', pet_name='harry')

Default Values

When writing a function, you can define a default value for each parameter.
If an argument for a parameter is provided in the function call, Python
uses the argument value. If not, it uses the parameter’s default value.

When you use default values, any parameter with a default value needs to be listed
after all the parameters that don’t have default values. This allows Python to continue interpreting positional arguments correctly.

1
2
3
4
5
def describe_pet(pet_name, animal_type='dog'):
"""Display information about a pet."""
print(f"\nI have a {animal_type}.")
print(f"My {animal_type}'s name is {pet_name.title()}.")
describe_pet(pet_name='willie')

I have a dog.
My dog’s name is Willie.

describe_pet(‘willie’)
describe_pet(pet_name=’harry’, animal_type=’hamster’)

Equivalent Function Calls

Because positional arguments, keyword arguments, and default values can
all be used together, you’ll often have several equivalent ways to call a function

1
2
3
4
5
6
7
8
def describe_pet(pet_name, animal_type='dog'):
# A dog named Willie.
describe_pet('willie')
describe_pet(pet_name='willie')
# A hamster named Harry.
describe_pet('harry', 'hamster')
describe_pet(pet_name='harry', animal_type='hamster')
describe_pet(animal_type='hamster', pet_name='harry')

Avoiding Argument Errors

1
2
3
4
5
def describe_pet(animal_type, pet_name):
"""Display information about a pet."""
print(f"\nI have a {animal_type}.")
print(f"My {animal_type}'s name is {pet_name.title()}.")
describe_pet()
1
2
3
4
5
6
7
Traceback (most recent call last):
File "pets.py", line 6, in <module>
describe_pet()
^^^^^^^^^^^^^^
TypeError: describe_pet() missing 2 required positional arguments:
'animal_type' and 'pet_name'

Return Values

1
2
3
4
5
6
def get_formatted_name(first_name, last_name):
"""Return a full name, neatly formatted."""
full_name = f"{first_name} {last_name}"
return full_name.title()
musician = get_formatted_name('jimi', 'hendrix')
print(musician)

Making an Argument Optional

1
2
3
4
5
6
7
8
def get_formatted_name(first_name, middle_name, last_name):
"""Return a full name, neatly formatted."""
full_name = f"{first_name} {middle_name} {last_name}"
return full_name.title()
musician = get_formatted_name('john', 'lee', 'hooker')
print(musician)
musician = get_formatted_name('jimi', 'hendrix')
print(musician)

John Lee Hooker
Jimi Hendrix

Returning a Dictionary

1
2
3
4
5
6
7
8
def build_person(first_name, last_name, age=None):
"""Return a dictionary of information about a person."""
person = {'first': first_name, 'last': last_name}
if age:
person['age'] = age
return person
musician = build_person('jimi', 'hendrix', age=27)
print(musician)

Using a Function with a while Loop

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def get_formatted_name(first_name, last_name):
"""Return a full name, neatly formatted."""
full_name = f"{first_name} {last_name}"
return full_name.title()
while True:
print("\nPlease tell me your name:")
print("(enter 'q' at any time to quit)")
f_name = input("First name: ")
if f_name == 'q':
break
l_name = input("Last name: ")
if l_name == 'q':
break
formatted_name = get_formatted_name(f_name, l_name)
print(f"\nHello, {formatted_name}!")

Passing a List

1
2
3
4
5
6
7
def greet_users(names):
"""Print a simple greeting to each user in the list."""
for name in names:
msg = f"Hello, {name.title()}!"
print(msg)
usernames = ['hannah', 'ty', 'margot']
greet_users(usernames)

Hello, Hannah!
Hello, Ty!
Hello, Margot!

Modifying a List in a Function

1
2
3
4
5
6
7
8
9
10
11
12
13
# Start with some designs that need to be printed.
unprinted_designs = ['phone case', 'robot pendant', 'dodecahedron']
completed_models = []
# Simulate printing each design, until none are left.
# Move each design to completed_models after printing.
while unprinted_designs:
current_design = unprinted_designs.pop()
print(f"Printing model: {current_design}")
completed_models.append(current_design)
# Display all completed models.
print("\nThe following models have been printed:")
for completed_model in completed_models:
print(completed_model)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
def print_models(unprinted_designs, completed_models):
"""
Simulate printing each design, until none are left.
144 Chapter 8
Move each design to completed_models after printing.
"""
while unprinted_designs:
current_design = unprinted_designs.pop()
print(f"Printing model: {current_design}")
completed_models.append(current_design)
def show_completed_models(completed_models):
"""Show all the models that were printed."""
print("\nThe following models have been printed:")
for completed_model in completed_models:
print(completed_model)
unprinted_designs = ['phone case', 'robot pendant', 'dodecahedron']
completed_models = []
print_models(unprinted_designs, completed_models)
show_completed_models(completed_models)

Preventing a Function from Modifying a List

You can send a copy of a list to a function like this:
function_name(list_name[:])

print_models(unprinted_designs[:], completed_models)

Passing an Arbitrary Number of Arguments

1
2
3
4
5
def make_pizza(*toppings):
"""Print the list of toppings that have been requested."""
print(toppings)
make_pizza('pepperoni')
make_pizza('mushrooms', 'green peppers', 'extra cheese')

(‘pepperoni’,)
(‘mushrooms’, ‘green peppers’, ‘extra cheese’)

1
2
3
4
5
6
7
8
def make_pizza(*toppings):
"""Summarize the pizza we are about to make."""
Functions 147
print("\nMaking a pizza with the following toppings:")
for topping in toppings:
print(f"- {topping}")
make_pizza('pepperoni')
make_pizza('mushrooms', 'green peppers', 'extra cheese')

Making a pizza with the following toppings:

  • pepperoni
    Making a pizza with the following toppings:
  • mushrooms
  • green peppers
  • extra cheese

Mixing Positional and Arbitrary Arguments

If you want a function to accept several different kinds of arguments, the
parameter that accepts an arbitrary number of arguments must be placed
last in the function definition. Python matches positional and keyword
arguments first and then collects any remaining arguments in the final
parameter.

1
2
3
4
5
6
7
def make_pizza(size, *toppings):
"""Summarize the pizza we are about to make."""
print(f"\nMaking a {size}-inch pizza with the following toppings:")
for topping in toppings:
print(f"- {topping}")
make_pizza(16, 'pepperoni')
make_pizza(12, 'mushrooms', 'green peppers', 'extra cheese')

Making a 16-inch pizza with the following toppings:

  • pepperoni

Making a 12-inch pizza with the following toppings:

  • mushrooms
  • green peppers
  • extra cheese

Using Arbitrary Keyword Arguments

def build_profile(first, last, **user_info):
“””Build a dictionary containing everything we know about a user.”””
user_info[‘first_name’] = first
user_info[‘last_name’] = last
return user_info
user_profile = build_profile(‘albert’, ‘einstein’,
location=’princeton’,
field=’physics’)
print(user_profile)

{‘location’: ‘princeton’, ‘field’: ‘physics’,
‘first_name’: ‘albert’, ‘last_name’: ‘einstein’}

write functions that accept as many key-value
pairs as the calling statement provides

You’ll often see the parameter name **kwargs used to collect nonspecific keyword
arguments.

Storing Your Functions in Modules

storing your functions in a separate file called a module and then importing
that module into your main program. An import statement tells Python to
make the code in a module available in the currently running program file

Importing an Entire Module

1
2
3
4
5
def make_pizza(size, *toppings):
"""Summarize the pizza we are about to make."""
print(f"\nMaking a {size}-inch pizza with the following toppings:")
for topping in toppings:
print(f"- {topping}")

import pizza
pizza.make_pizza(16, ‘pepperoni’)
pizza.make_pizza(12, ‘mushrooms’, ‘green peppers’, ‘extra cheese’)

Importing Specific Functions

from module_name import function_name

from module_name import function_0, function_1, function_2

1
2
3
from pizza import make_pizza
make_pizza(16, 'pepperoni')
make_pizza(12, 'mushrooms', 'green peppers', 'extra cheese')

Using as to Give a Function an Alias

1
2
3
from pizza import make_pizza as mp
mp(16, 'pepperoni')
mp(12, 'mushrooms', 'green peppers', 'extra cheese')

Using as to Give a Module an Alias

1
2
3
import pizza as p
p.make_pizza(16, 'pepperoni')
p.make_pizza(12, 'mushrooms', 'green peppers', 'extra cheese')

Importing All Functions in a Module

from pizza import *
make_pizza(16, ‘pepperoni’)
make_pizza(12, ‘mushrooms’, ‘green peppers’, ‘extra cheese’)

The best approach is to import the function or functions you want, or
import the entire module and use the dot notation. This leads to clear code
that’s easy to read and understand

Classes

Creating and Using a Class

1
2
3
4
5
6
7
8
9
10
11
12
class Dog:
"""A simple attempt to model a dog."""
def __init__(self, name, age):
"""Initialize name and age attributes."""
self.name = name
self.age = age
def sit(self):
"""Simulate a dog sitting in response to a command."""
print(f"{self.name} is now sitting.")
def roll_over(self):
"""Simulate rolling over in response to a command."""
print(f"{self.name} rolled over!")

The __init__() method is a special method
that Python runs automatically whenever we create a new instance based
on the Dog class. This method has two leading underscores and two trailing underscores, a convention that helps prevent Python’s default method
names from conflicting with your method names.

The self parameter is required in the method definition, and
it must come first, before the other parameters. It must be included in
the definition because when Python calls this method later (to create an
instance of Dog), the method call will automatically pass the self argument.
Every method call associated with an instance automatically passes self,
which is a reference to the instance itself; it gives the individual instance
access to the attributes and methods in the class

Making an Instance from a Class

1
2
3
my_dog = Dog('Willie', 6)
print(f"My dog's name is {my_dog.name}.")
print(f"My dog is {my_dog.age} years old.")

My dog’s name is Willie.
My dog is 6 years old.

Calling Methods

1
2
3
4
5
class Dog:
--snip--
my_dog = Dog('Willie', 6)
my_dog.sit()
my_dog.roll_over()

Willie is now sitting.
Willie rolled over!

Creating Multiple Instances

1
2
3
4
5
6
7
8
9
10
class Dog:
--snip--
my_dog = Dog('Willie', 6)
your_dog = Dog('Lucy', 3)
print(f"My dog's name is {my_dog.name}.")
print(f"My dog is {my_dog.age} years old.")
my_dog.sit()
print(f"\nYour dog's name is {your_dog.name}.")
print(f"Your dog is {your_dog.age} years old.")
your_dog.sit()

My dog’s name is Willie.
My dog is 6 years old.
Willie is now sitting.
Your dog’s name is Lucy.
Your dog is 3 years old.
Lucy is now sitting.

Working with Classes and Instances

1
2
3
4
5
6
7
8
9
10
11
12
13
class Car:
"""A simple attempt to represent a car."""
def __init__(self, make, model, year):
"""Initialize attributes to describe a car."""
self.make = make
self.model = model
self.year = year
def get_descriptive_name(self):
"""Return a neatly formatted descriptive name."""
long_name = f"{self.year} {self.make} {self.model}"
return long_name.title()
my_new_car = Car('audi', 'a4', 2024)
print(my_new_car.get_descriptive_name())

2024 Audi A4

Setting a Default Value for an Attribute

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Car:
def __init__(self, make, model, year):
"""Initialize attributes to describe a car."""
self.make = make
self.model = model
self.year = year
self.odometer_reading = 0
def get_descriptive_name(self):
--snip--
def read_odometer(self):
"""Print a statement showing the car's mileage."""
print(f"This car has {self.odometer_reading} miles on it.")
my_new_car = Car('audi', 'a4', 2024)
print(my_new_car.get_descriptive_name())
my_new_car.read_odometer()

2024 Audi A4
This car has 0 miles on it.

Modifying Attribute Values

Modifying an Attribute’s Value Directly
1
2
3
4
5
6
class Car:
--snip--
my_new_car = Car('audi', 'a4', 2024)
print(my_new_car.get_descriptive_name())
my_new_car.odometer_reading = 23
my_new_car.read_odometer()

2024 Audi A4
This car has 23 miles on it.

Modifying an Attribute’s Value Through a Method
1
2
3
4
5
6
7
8
class Car:
--snip--
def update_odometer(self, mileage):
"""Set the odometer reading to the given value."""
self.odometer_reading = mileage
my_new_car = Car('audi', 'a4', 2024)
my_new_car.update_odometer(23)
my_new_car.read_odometer()

2024 Audi A4
This car has 23 miles on it.

1
2
3
4
5
6
7
8
9
10
11
class Car:
--snip--
def update_odometer(self, mileage):
"""
Set the odometer reading to the given value.
Reject the change if it attempts to roll the odometer back.
"""
if mileage >= self.odometer_reading:
self.odometer_reading = mileage
else:
print("You can't roll back an odometer!")
Incrementing an Attribute’s Value Through a Method
1
2
3
4
5
6
7
8
9
10
11
12
13
class Car:
--snip--
def update_odometer(self, mileage):
--snip--
def increment_odometer(self, miles):
"""Add the given amount to the odometer reading."""
self.odometer_reading += miles
my_used_car = Car('subaru', 'outback', 2019)
print(my_used_car.get_descriptive_name())
2 my_used_car.update_odometer(23_500)
my_used_car.read_odometer()
my_used_car.increment_odometer(100)
my_used_car.read_odometer()

2019 Subaru Outback
This car has 23500 miles on it.
This car has 23600 miles on it.

Inheritance

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class Car:
"""A simple attempt to represent a car."""
def __init__(self, make, model, year):
"""Initialize attributes to describe a car."""
self.make = make
self.model = model
self.year = year
self.odometer_reading = 0
def get_descriptive_name(self):
"""Return a neatly formatted descriptive name."""
long_name = f"{self.year} {self.make} {self.model}"
return long_name.title()
def read_odometer(self):
"""Print a statement showing the car's mileage."""
print(f"This car has {self.odometer_reading} miles on it.")
def update_odometer(self, mileage):
"""Set the odometer reading to the given value."""
if mileage >= self.odometer_reading:
self.odometer_reading = mileage
else:
print("You can't roll back an odometer!")
def increment_odometer(self, miles):
"""Add the given amount to the odometer reading."""
self.odometer_reading += miles

class ElectricCar(Car):
"""Represent aspects of a car, specific to electric vehicles."""
def __init__(self, make, model, year):
"""Initialize attributes of the parent class."""
super().__init__(make, model, year)
my_leaf = ElectricCar('nissan', 'leaf', 2024)
print(my_leaf.get_descriptive_name())

2024 Nissan Leaf

Defining Attributes and Methods for the Child Class

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Car:
--snip--
class ElectricCar(Car):
"""Represent aspects of a car, specific to electric vehicles."""
def __init__(self, make, model, year):
"""
Initialize attributes of the parent class.
Then initialize attributes specific to an electric car.
"""
super().__init__(make, model, year)
self.battery_size = 40
def describe_battery(self):
"""Print a statement describing the battery size."""
print(f"This car has a {self.battery_size}-kWh battery.")
my_leaf = ElectricCar('nissan', 'leaf', 2024)
print(my_leaf.get_descriptive_name())
my_leaf.describe_battery()

2024 Nissan Leaf
This car has a 40-kWh battery.

Overriding Methods from the Parent Class

the class Car had a method called fill_gas_tank(). This method is
meaningless for an all-electric vehicle, so you might want to override this
method

1
2
3
4
5
class ElectricCar(Car):
--snip--
def fill_gas_tank(self):
"""Electric cars don't have gas tanks."""
print("This car doesn't have a gas tank!")

Instances as Attributes

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Battery:
"""A simple attempt to model a battery for an electric car."""
def __init__(self, battery_size=40):
"""Initialize the battery's attributes."""
self.battery_size = battery_size
def describe_battery(self):
"""Print a statement describing the battery size."""
print(f"This car has a {self.battery_size}-kWh battery.")

class ElectricCar(Car):
"""Represent aspects of a car, specific to electric vehicles."""
def __init__(self, make, model, year):
"""Initialize attributes of the parent class."""
super().__init__(make, model, year)
self.battery = Battery()


my_leaf = ElectricCar('nissan', 'leaf', 2024)
print(my_leaf.get_descriptive_name())
my_leaf.battery.describe_battery()

2024 Nissan Leaf
This car has a 40-kWh battery.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Car:
--snip--
class Battery:
--snip--
def get_range(self):
"""Print a statement about the range this battery provides."""
if self.battery_size == 40:
range = 150
elif self.battery_size == 65:
range = 225
print(f"This car can go about {range} miles on a full charge.")
class ElectricCar(Car):
--snip--
my_leaf = ElectricCar('nissan', 'leaf', 2024)
print(my_leaf.get_descriptive_name())
my_leaf.battery.describe_battery()
my_leaf.battery.get_range()

Importing Classes

Importing a Single Class

car.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
"""A class that can be used to represent a car."""
class Car:
"""A simple attempt to represent a car."""
def __init__(self, make, model, year):
"""Initialize attributes to describe a car."""
self.make = make
self.model = model
self.year = year
self.odometer_reading = 0
def get_descriptive_name(self):
"""Return a neatly formatted descriptive name."""
long_name = f"{self.year} {self.make} {self.model}"
return long_name.title()
def read_odometer(self):
"""Print a statement showing the car's mileage."""
print(f"This car has {self.odometer_reading} miles on it.")
def update_odometer(self, mileage):
"""Set the odometer reading to the given value."""
if mileage >= self.odometer_reading:
self.odometer_reading = mileage
else:
print("You can't roll back an odometer!")
def increment_odometer(self, miles):
"""Add the given amount to the odometer reading."""
self.odometer_reading += miles

my_car.py

1
2
3
4
5
from car import Car
my_new_car = Car('audi', 'a4', 2024)
print(my_new_car.get_descriptive_name())
my_new_car.odometer_reading = 23
my_new_car.read_odometer()

2024 Audi A4
This car has 23 miles on it.

Storing Multiple Classes in a Module

car.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
"""A set of classes used to represent gas and electric cars."""
class Car:
--snip--

class Battery:
"""A simple attempt to model a battery for an electric car."""
def __init__(self, battery_size=40):
"""Initialize the battery's attributes."""
self.battery_size = battery_size
def describe_battery(self):
"""Print a statement describing the battery size."""
print(f"This car has a {self.battery_size}-kWh battery.")

def get_range(self):
"""Print a statement about the range this battery provides."""
if self.battery_size == 40:
range = 150
elif self.battery_size == 65:
range = 225
print(f"This car can go about {range} miles on a full charge.")

class ElectricCar(Car):
"""Represent aspects of a car, specific to electric vehicles."""
def __init__(self, make, model, year):
"""Initialize attributes of the parent class."""
super().__init__(make, model, year)
self.battery = Battery()

my_electric_car.py

1
2
3
4
5
from car import ElectricCar
my_leaf = ElectricCar('nissan', 'leaf', 2024)
print(my_leaf.get_descriptive_name())
my_leaf.battery.describe_battery()
my_leaf.battery.get_range()

2024 Nissan Leaf
This car has a 40-kWh battery.
This car can go about 150 miles on a full charge.

Importing Multiple Classes from a Module

1
2
3
4
5
from car import Car, ElectricCar
my_mustang = Car('ford', 'mustang', 2024)
print(my_mustang.get_descriptive_name())
my_leaf = ElectricCar('nissan', 'leaf', 2024)
print(my_leaf.get_descriptive_name())

2024 Ford Mustang
2024 Nissan Leaf

Importing an Entire Module0

1
2
3
4
5
import car
my_mustang = car.Car('ford', 'mustang', 2024)
print(my_mustang.get_descriptive_name())
my_leaf = car.ElectricCar('nissan', 'leaf', 2024)
print(my_leaf.get_descriptive_name())

Importing All Classes from a Module

from module_name import *

This method is not recommended for two reasons. First, it’s helpful to be
able to read the import statements at the top of a file and get a clear sense of
which classes a program uses. With this approach it’s unclear which classes
you’re using from the module. This approach can also lead to confusion
with names in the file. If you accidentally import a class with the same name
as something else in your program file, you can create errors that are hard
to diagnose.

Importing a Module into a Module

car.py

“””A class that can be used to represent a car.”””
class Car:
–snip–

electric_car.py

“””A set of classes that can be used to represent electric cars.”””
from car import Car
class Battery:
–snip–
class ElectricCar(Car):
–snip–

my_cars.py

1
2
3
4
5
6
from car import Car
from electric_car import ElectricCar
my_mustang = Car('ford', 'mustang', 2024)
print(my_mustang.get_descriptive_name())
my_leaf = ElectricCar('nissan', 'leaf', 2024)
print(my_leaf.get_descriptive_name())

Using Aliases

from electric_car import ElectricCar as EC
my_leaf = EC(‘nissan’, ‘leaf’, 2024)

import electric_car as ec
my_leaf = ec.ElectricCar(‘nissan’, ‘leaf’, 2024)

Files and Exceptions

Testing Your Code