Transcripts
1. Course Introduction: Welcome to PyTon
Visually Explain a course designed to teach you
programming using PyTon. In this course, we use
visual representations to illustrate concepts and make
programming accessible. By taking this course, you learn the fundamentals
of programming and use those concepts to solve
real world problems. To support you on
your PTN journey, you'll have two experienced
mentors by your side. My name is Sebastian. I'm a finance professor at the University of
Wisconsin Madison. I've been using PyTon
extensively for many years, both for my academic research
and in the classroom. And I'm Ali, the teaching
assistant for this course. I hold a double major in
computer science and finance, also from the University
of Wisconsin Madison. Whether you're a complete
beginner or have some experience programming
in other languages, this course will teach
you valuable skills. Beginners will get the
chance to learn the basics comfortably as we don't assume any prior
programming knowledge. The first lectures of
this course introduce fundamental concepts such
as variable assignments. We then build on
those foundations to study more complex
topics like for loops. Finally, we'll show
you how to unlock new capabilities by tapping
into Python libraries, giving you endless tools
to solve problems from creating graphs to performing language translation
and much more. This modular structure
is also great for experienced programmers
interested in specific aspects of
the Python language. You can jump directly
to topics of interest and familiarize
yourself with the Python syntax. We have developed this course
to be clear and concise. We respect your time as a learner and want to help you learn concepts efficiently. Each concept in this course, has its own dedicated
module with several videos. Every module kicks off with one or two introductory videos, giving you a basic
understanding of the concept through visual explanations
and code examples. Then we dive deeper with videos that explore more
advanced use cases. In these videos, you'll join Jamie and Pike on their
hiking Adventures, where they encounter problems
that we solve in Python. Doing so allows us to see how concepts we've
learned can be applied. Then to deepen your
understanding of the concepts, we provide exercise notebooks that you can work
on independently. These exercises will
allow you to master each topic and often
introduce new related ideas. Following each
exercise workbook is a video walking through the
solutions to the exercises. These videos break down
each problem step by step using clear visuals
to support your learning. Every module has
an associated file on our course Github page. This file contains links to notebooks we
use in the videos, exercise notebooks, and
extra learning resources. Feel free to explore
the resources and follow along with the videos
in the provided notebooks. Finally, at the
end of the course, you will work on a
project where you apply your new programming skills to create a language
translator application. I'm a little biased,
but it's a lot of fun. We're excited to have
you on this journey. No matter where
you're starting from, this course is designed to make programming
concepts intuitive, practical, and enjoyable.
Let's get started.
2. Getting Started with Colab: This video, we will introduce the Python coding environment
used in this course. It's called Google
Collaboratory or Colab. Colab is a great
environment for learning programming because it's
free and cloud based, meaning you can access it from any computer without
installing any software. Setting up Colab is very easy. All you need is a
Google account. If you use Gmail, Google Drive, or Google
Calendar, good news. You already have an account. But if you don't, you can create an account
for free by going to accounts google.com
slash SINAP. Once you've signed
up, navigate to your Google Drive
where you'll be able to create your
first Colab notebook. To create a new Notebook, click the New button. Go to Me and you may or may not see the
Google Colaboratory option. If you do not see
Colab as an option, that means we need
to install it. Click Connect More Apps
and search Collaboratory. Then click on Collaboratory
and install it. You will be presented with
a few permission dialogues before Colab is installed. Awesome. Now let's create a notebook and explore the
basic functionality of Colab. Every notebook is divided into cells where we can write
code or other text. To create a new
cell, hover over the top or bottom edge
of an existing cell. Here, we see that there
are two types of cells. Code cells, like the one
that already exists, are where we write
our Python code. Text cells are for
anything that isn't code. Optionally, we can format
cells using Markdown, which we won't cover
in this course. If you want to learn
more about Markdown, there is a helpful link on the GitHub page for this module. Additionally, we can change
the order of cells using the arrows and remove cells
by clicking the trash icon. Eight. While you
might want to create notebooks from scratch
for your own projects, in this course, we will provide notebooks
for every video. You can access every
notebook through the notebook Links
page in this module. This link will take you to a GitHub page where
you'll find a file for each module with links to notebooks and other
relevant information. When you click a Notebook link, you will be taken to a read
only copy of the Notebook. To make your own copy, click
the copy to drive button in the toolbar and Colab will
create a copy in a new tab. You now own this copy of the Notebook and it is
saved to your Google Drive. This means that you can edit the cells and the notebook name. To view the list of
your Colab notebooks, click the logo in the upper left corner to go
to Google Drive. Alternatively, you
can access the course notebooks that you copy to your drive in the Colab
notebooks folder. Great. These are
all the features of Colab that we
need to get started. As we progress
through this course, we'll explore Clob's
functionality a lot more. So don't worry if this interface seems a little
intimidating right now. When we tackle our first topic, we will learn how to write
and run code in a notebook. And with that, let's dive in.
3. Numeric Operations: Welcome to the first
programming concept of this course
numeric operators. In this video, we
will see how to use numeric operators to perform basic mathematical
operations in PyTon. The concepts covered in this
video are quite simple. Which is a good thing
as it will allow us to gently familiarize
ourselves with the Google Colab environment. In Bton, numeric
operators such as plus, minus star and slash can perform mathematical
operations on numbers much like you learned
in grade school. For example, if
we are interested in calculating the
sum of two and three, we can write two plus
three in a code cell. Then to evaluate the expression, we must instruct Python
to execute the code. In Google Colab, this
is done by clicking the Run button on the left
of the code cell or by pressing the keys
Control plus Enter or Command plus return depending
on your operating system. Congratulations. You have now executed your very
first line of code. Unsurprisingly,
PyTon reports that the value of two
plus three is five. Similarly, if we want to
subtract three from two, we use the subtraction operator minus to multiply two and three, we use the multiplication
operator star and to divide two by three, we use the division operator. In each cases, when we
run the code cells, we obtain the expected
answers. Great. We have now run our first
few lines of Byton code. That was easy, wasn't it? In the next video, we will see a few examples of use cases for the operators we
covered in this video and we'll introduce a
few more operators.
4. Numeric Operations - Guided Examples: Jamie is excited about her
upcoming weekend hike. But before she ventures
into the wilderness, she must plan accordingly. In particular, she must determine how many
miles she will hike, how long she will be gone, how much water to
carry, and so on. Miles, time, and ounces of
water are all about numbers. And since Matt is not
Jamie's strong suit, she will ask Bike to perform
a few calculations for her. One of Jamie's health
goal is to walk at least 10,000 steps daily. She'd like to meet that
goal during our hike. To meet our objective, how many miles long
should our hike be given that our average
stride length is 2.5 feet. While Pike computes the answer, let's see if we can solve
the problem using Piton. First, to fight the distance
in feet Jamie needs to hike, we must multiply her step goal 10,000 by our stride
length, 2.5 feet. Executing the cell, we obtain
a result of 25,000 feet. Now, let's convert this
quantity into miles. We do this by dividing
our previous result by 5,280 the number
of feet per mile. Executing the cell,
we obtain 4.73 miles, and so does Pike. Based on that information, Pike suggests to hike a local trail called
the roller coaster. However, it cautions Jamie
that this trail features some challenging
climb with a total of 500 feet of elevation gain. From Jamie's
perspective, though, elevation gains make hiking a trail exponentially more fun. Because Jamie likes to quantify all aspects
of her adventures, she asks Pike to calculate how many units of fun she will have hiking the
roller coaster trail. According to her, the fun of a hike is calculated
as the elevation gain squared plus a baseline of 1,000 units of fun for
simply getting outside. Let's make the calculation
in the notebook. To implement the formula, we need to square
the elevation gain. In Pyton, the exponent
operator is the double star. We complete the
expression by adding an extra 1,000 units of fun
for just getting outside. When we execute the cell, we obtain 251,000 units of fun. And so does Pike. That's all good, but with lots of fun comes lots
of responsibilities. Jamie must ensure she stays well hydrated
during the hike. From previous experience,
she knows that a hike that long will require
40 ounces of water. To carry water, Jamie
has 512 ounce bottles. She is interested in finding out the number of bottles
that need to be filled, and if applicable, she wants to know the
volume that should be added to the last
bottle in order to have a total of 40 ounces of water. We can, of course, find this quantity using the
regular division operator. By calculating 40/12,
we obtain 3.33. This indicates that Jamie
needs three full bottles and a fourth bottle
filled to one third of its capacity or 4 ounces. This method works,
but PyTon provides two other operators that make this calculation
just a bit easier, the floor division and
modulus operators. The floor division
operator returns the number of times the
divisor, in this case, 12 goes evenly
into the dividend, in this case, 40. In our example, the expression
yields a results of three, indicating that Jimmy requires three full bottles of water. Note that the floor
division operator yields the integer part of the regular
division's outcome, discarding any
fractional component. Awesome. Let's now talk
about the modulus operator. The modulus operator
returns the remainder or the leftovers
after floor division. In our example, the
leftovers after floor division is four.
And look at that. Pike agrees with our assessment. We now know all of PyTon's
arithmetic operators. In the next video, we'll gain some practice with those
numeric operations.
5. Introduction to Data Types: Previous video, we wrote multiple numbers
in our notebook. Some were numbers, and
others were decimal numbers. The Python language makes a formal distinction between these two types of
numeric values. In this video, we'll explore this distinction as we introduce
the notion of datatype. Whole numbers, that is any
positive or negative number without a fractional component are called integers
in programming. For their part, decimal numbers, that is any positive or
negative number with a fractional component,
are called floats. Let's confirm that Piton indeed makes a distinction between
these two types of numbers. To verify the existence
of that distinction, we will use the built
in function type. We will discuss built in functions in detail
in a future video. For now, let's take as
given that writing type, followed by a number
between parentheses, instruct PyTon to output whether the number is an
integer or a float. For example, if we
write the number 13 inside parentheses
and execute the cell, PyTon outputs int this means that the value 13 is of
the integer data type. Similarly, if we
write the number 3.14 15 inside the parentheses,
we obtain float. In PyTon, the
distinction between integers and floats is
somewhat technical. There are contexts where
this distinction matters, but for the applications we
consider in this course, it won't really matter. Important general concept
to take away from this video is the
notion of data type. BTN can represent
various types of data, including integers and float, but also several more. Over the course of
these lectures, we'll cover many more data
types and explore their use. But before we go
there, let's solve a few exercises on integers and floats to
gain some practice.
6. Numeric Operations and Data Types - Exercise Solutions: In this workbook,
you practiced using Python's numeric operators
and the type function. Let's go through the solutions. To solve exercise one, part A, we can use the
multiplication operator. Just multiply the number
of loaves by the weight of flour per loaf and then
by the cost per kilo. The owner's total
cost is $12.65. We can also check the type of our cost using the
type function. Because of the decimal places, we would expect
$12.65 to be afloat. And Python agrees.
For exercise two, we can find the
total cook time for the 200 cookies by using parentheses to group
terms together. Because we have two ovens
with a 25 cookie capacity, we can multiply 25 by two to get the
total cookie capacity. Then we divide the
200 cookies we need to bake by this expression, grouping it with parentheses to ensure the correct
order of operations. This results in the number of batches we need to
cook in the oven. Finally, we can multiply this expression by 15 minutes
to get the total time. Again, we use parentheses to ensure proper
order of operations. Executing the cell,
we get that it will take 60 minutes to
bake all the cookies. If we do not use parentheses, we will get 240,
which is incorrect. Again, we can check the type of R result using the
type function. 60.0 is a float because it
has a decimal component, even though the decimal
component is zero. Moving to exercise three, we can calculate the number of full batches using the
floor division operator. 250 grams of chocolate chips, floor divided by 40 grams
per batch, results in six. We can calculate the
leftover grams of chocolate chips with
the modulus operator. When we have 250 grams of chocolate chips and need
40 grams per batch, we have 10 grams leftover
after six batches. Similarly, in Part B, we can use the floor division operator to calculate that if each pastry needs 37 grams of dough and we have
500 grams of dough, we can make 13 pastries. Using the modulus operator, we can also see
that there will be 19 grams of dough leftover. Great. In exercise four, we can capture the fact
that the yeast doubles in mass every hour with
the exponent operator. If the yeast is allowed
to grow for 6 hours, we raise two to
the power of six. Then we multiply that by the starting
grams of yeast three to get the result of 192
grams after 6 hours. Finally, in exercise five, to calculate the
weight of the flour, we simply multiply
20 by 23 to get 460. Next, to calculate the
weight of the sugar, we can use the
exponent operator to find the square root of
the weight of the flour, 460 to get 21.45. Then, we use the modulus
operator to find the remainder of the total
flour and sugar divided by 42, which results in 19.45. Finally, the total
weight is the sum of the three ingredients
and is 500.9. In Part B, we can reuse
the total weight of the ingredients and utilize
regular division to see that the owner
can make 8.04 batches with 62.3 grams of
ingredients per batch. However, because the
owner cannot make 0.04 of a batch, we
should round down. We can do this using the floor division
operator to retrieve only the whole
number component of the division result,
which is eight. Great. Now that you understand numeric operations and
the type function, we are ready to start
exploring another of Python's data types strings.
7. Strings: So far, in our journey
through PyTn's data type, we have covered
integers and flows, which are the foundation of numeric representation
in programming. Moreover, we have seen several operators that perform mathematical operations
on numeric values. Now, let's shift gear and venture into the world
of textual data. In this video, we'll
introduce you to strings, an essential data type used
to represent text in PyTon. Strings open up a
whole new world of possibilities in programming
from processing user inputs, to creating large
language models. By the end of this lesson, you'll know how to create and manipulate strings in Python. In programming, being able to represent textual
data is often useful. For example, a grade
assignment program may need to represent
the letter A. Similarly, a spell checker
program might need to represent the contents of
long text like the Odyssey. In Python, textual data, such as a single letter or the Odyssey poem are
managed using strings. To create a string, we enclose the
desired characters between single or
double quotation marks. For example, to
represent the letter A, we can type the letter
A in a code cell and surround it with single
quotation marks as follows. Similarly, to represent
the entire content of the Odyssey poem, we can bracket the
book's content with single or double quotation
marks as follows. Note that the quotes are not
part of the string itself. They are there to delimit where the string
begins and ends. Also, note that
strings can be used to represent numbers and
other special characters. Wait a minute. What
did I just say? Strings can be used
to represent numbers. So why do we need integers and
floats in the first place? Aren't string enough
by themselves? The answer is no. As we are about to see, Biton makes an
important distinction between numbers that
are expressed as integers or floats and numbers that are
expressed as strings. For example, let's say that we want to evaluate the
sum of one and two. If we represent these numbers
using integers or floats, we obtain the number
three as expected. But if we represent
these numbers using strings and evaluate the
expression, what do we get? We got 12. Wow. That's
some new age mathematics right there. What happened? Well, as you may have guessed, when we work with strings, the plus operator means something different than when we work with numeric values. With numeric values, the plus operator
performs an addition. With strings, the plus operator
ties strings together. As this example shows, data types can influence the behavior of a
given operator. This in turn creates an important distinction
between various datatypes. In Piton, data types determine the behavior
of the operators we use. In the next video,
we will explore some operations that are
specific to strings.
8. Strings - Guided Examples: Jamie and Pike have just started their hike on the rugged
Roller Coaster trail. Despite its name,
the first part of the roller coaster trail is well maintained and mostly flat. Jamie relaxes as she enjoys the mountain scenery and the
fresh smell of pine trees. Wonderful. However, half
an hour into the hike, the Roller Coaster trail
takes back its name. Indeed, in front
of Jamie and Pike looms a 15 foot deep ravine
splitting the trail. To get across, our two hikers will need the rope they
fortunately brought. While Jamie and Pike manipulate robes to
solve their problem, we will study how
manipulating piton strings can help programmers tackle
analogous challenges. Before initiating the descent, Jamie asks Pike to scan
the rope for defects. Safety first, Pike
carefully checks the rope and represents the scan results
using characters. If a given foot of
rope is defect free, it is represented by
the dash character. However, if the scan
reveals a defect, that foot of the rope is represented by the
star character. Let's represent the results of Pike scan in Piton
using a string. Unfortunately, as you can see, there is a defect in the rope. Jamie should have checked
it before leaving. But now that she's aware of it, she wants to find out exactly where the defect is
located on the rope. Since in our code, each character
represents 1 ft of rope, we can visually
inspect the string and see that the defect is
the ninth character. That is, it is on the
ninth foot of the rope. Let's see if Biton agrees
with our visual inspection. When we know the position
of a character in a string, we can ask Python to output that character by
indexing the string. To index a string, we must append a pair of
brackets at the end of it and provide the position of the desired character in
between the brackets. The number we write in between the brackets is called the
index of the character. So, surely, when we
execute this code, we will obtain the
character star, right? Oh, well, that's unexpected. Why do we get a dash character? The reason is that in Bton, the characters of
a string are index starting from zero
and not from one. When we access the character
located at index nine, we actually pull
the tenth character of the string, not the ninth. We can get the defect
character as output by changing our index to eight
and re running our cell. All right. Now that Jimmy
knows where the defect is, she wants to remove
it from the rope. Always a good helper, Pike
slices the rope before and after the defect
and is left with two defect free pieces of rope. We can achieve a
similar result in Python by slicing the string. But while indexing returns
a single character, slicing allows us to retrieve multiple
adjacent characters. To slice a string, we start by appending a pair of brackets
at the end of the string. Then between the brackets, we first write the index of the first character
we want to retrieve. For example, to get the first defect free
section of the road, we start by writing zero. We follow that first
index with a column. Then we specify the index of the last character
we want plus one. This means that in our example, to obtain the first characters
of the string up to and excluding the
defect, we write eight. When slicing a string, the character associated with the upper index is not return. I know. It can be
a bit confusing, but you'll get the opportunity to practice in the next video. For now, let's confirm that this piece of code
gives us what we want. When we run our code, we indeed obtain the first eight
characters of the string. Similarly, we can retrieve the other defect
free rope section by slicing the string from
index nine to index 19. Again, we achieve this by
writing 20 after the colon. Awesome. Jamie and Pike
got rid of the defect. Unfortunately, they
are now stuck with two pieces of rope that are too short to
cross the ravine. That's when Pike gets the brilliant idea to tie
the two pieces together. We can achieve an
analogous result in PyTon by using the
plus operator. Indeed, as we saw in
the previous video, the plus operator can be
used to join strings. In our current example, if we copy our previous
two string slices in a new cell and tie
plus in between them, Piton will tie them together. Note that in programming, the operation of joining two or more strings together
is called concatenation, and the plus sign is called
a concatenation operator. Awesome. Now that the two
ropes are tied together, Jamie must verify if the joint rope is still
at least 15 feet long. No worries if you do not have laser eyes or the patience
to count the characters. Biton has a built
in function called N that can do the
heavy lifting for us. The LN function can be used to determine
the length of a string, much like the type
function could be used to determine
the type of a number. To use the NN function, simply type the
strings in between the parentheses and
execute the code. We obtain that our string
is 19 characters long, which means that the
rope is 19 foot long, and that is enough rope
to cross the ravine. Our two hikers can move
on with their hike. But on our side, before we move on with our
Python journey, let's take a few minutes to practice
manipulating strings.
9. Strings - Exercise Solutions: In this workbook, you practiced string operations and also learned a few more useful
string related concepts. Let's discuss the solutions. To solve exercise one, we need to be mindful of the two ways of
creating strings. In Part A, our string
contains an apostrophe, so we must create the
string using double quotes. Otherwise, Python
thinks the apostrophe is part of the
string delimiters, and we will get an error
instead of a string. However, the opposite
is true in Part B. Because our string
contains double quotes, we must create the string
with single quotes. If we do use double quotes
to try to create the string, we will get an
error since Python assumes that the double quotes are part of the
string delmeters. To solve Exercise two part A, we use indexing to retrieve
the G from ground beef. Starting from index zero, the G is the seventh character, so we specify seven
between the brackets. This successfully retrieves G from our ingredients string. In part B, we can get the slice ground beef by specifying the index
range seven to 20. Remember, the end
index is exclusive. So because we want index 19
to be included in our string, we specify the
ending index as 20. Then in Part C, we
can use shorthand slicing notation to retrieve two slices of our
ingredients string. First, because the slice
onion starts at index zero, we don't need to
specify that index. We can simply write
colon five in between brackets to
access the onion slice. Next, we can get the slice
from spices to the end of the string by writing
the starting index 22, followed by a colon. We do not need to specify
the ending index since we want every index until the end of the string
included in our slice. Then in exercise three, part A, we can use the
concatenation operator to join multiple strings together
on a single line of code. In Part B, we can use the
star operator to quickly concatenate garlic clove twice
to our ingredients string. Finally, in Part C, we can use the len function to measure the final length
of our ingredients string, which is 143 characters. Great. Now you have a solid understanding of strings and the operations
that we can perform on them. In the next video, we
will tackle one of the most important and
foundational concepts in programming, variables.
10. Variables: In previous videos,
we have seen how to manipulate three
fundamental data types, integers, loads, and strings. This was a lot of
fun, but like me, you may have found
that constantly copy and pasting
values was tedious. In this video, we will
see how to manage values more efficiently
using variables. So what are variables exactly? In a programming context, you can think of variables as storage containers
that can hold data. The data we store in
variables can be of any type, including integers,
floats and strings. When creating a variable, we must give it a unique name. Think of this name as a
label for the container. Using a label that describes the value we store
is a good idea, since it makes it easier
to refer to it later. Let's see how variables
work through an example. Suppose that we want
to store the string that represents Jamie's
rope in a variable. This can be done by first preceding the string
with the symbol equal. In PyTon, the equal symbol is known as the
assignment operator. It tells PTN that we
want to put or assign the data on the
right hand side of the equal sign in
some storage space. To complete the assignment, we must type a variable name on the left hand side
of the equal sign. For example, we can type X, running the cell, we
see that the code executed without issue
from the green checkmark. Note that when assigning
a value to a variable, the value itself is not
reported in the output box. To output the content
of a variable, simply type the variable's name on the last line of the cell. Now, let's talk about our
variable name choice. It is a valid name in the sense that this code
executed without issue, but X is not very descriptive of what is in
the storage container. So let's pick a more
descriptive variable name. Here, I suggest that rope is a better variable name since it directly evokes what we
store in the variable. When we run our program, the code executes successfully, which tells us that rope is also a valued variable
name. This is great. With this statement,
we have been able to assign our string to
the variable rope. Now that we know how
to create variables, let's explore how to use them. In general, we can manipulate variables the same way we can manipulate the
values they store. Remember how we manipulated strings in the previous videos? We can still perform all those operations when our data is stored
in a variable. For example, we can
index the content of the variable rope by
appending brackets at the end of the variable name
and writing the index of the character we are interested
in between the brackets. Similarly, we can slice the content of rope using
index range notation. If we want, we can even create new variables to hold
the string slices. And to tie the left rope and
the right rope together, simply use the
concatenation operator with the two variable
names. Awesome. We now know how to
manipulate variables. But before we move on, let's say a few more things
about variable names. At this point, you
might be under the impression that any
variable name is suitable. However, this is not the case. There are a few constraints we must be aware of.
Let's dive into it. If you recall, our
concatenated rope string has a length of 19 characters. So if we wanted to
assign it to a variable, it might be tempting
to assign it to a variable named 19 foot rope. Let's try to do that. Whoop. Hmm. That doesn't seem
to work. Why not? Well, that's because
when naming variables, we must follow four rules. First, variable names
cannot start with numbers. Clearly, the variable name 19 foot rope violates this rule. That being said, besides
the first character, numbers can be included in any other part of
the variable name, including the last character. For example, variable
names like My var two and my second var are valid. This means that
to fix the error, we could use a name
like 19 foot rope or rope of 19 feet instead. As expected, these are
valid variable names. But let's still discuss
the other three rules. The second rule says
that letters, numbers, and underscores are
the only characters that we can use in
a variable name. Clearly, our variable name 19 foot rope does
follow this rule. But names like my Star var or M var exclamation
point or my var, in two words, do not. The name myvar in two words
also violates the third rule. Spaces are not allowed. Because variable names
cannot contain spaces, programmers commonly
separate words with the underscore character
for readability. That's what we did with our
variable name, 19 foot rope. Finally, the fourth
rule we must be aware of is that variable names
are case sensitive. This means that Python will
recognize 19 foot rope as a different variable
than 19 foot rope where we capitalize the
first letter of each word. Great. Variables are an
essential programming tool that will be key as we move into more
complex programming. In the next video, we'll
explore an application where using variables turns
out to be quite helpful.
11. Variables - Guided Examples: Jamie and Pike are
progressing quickly on the roller coaster trail despite the blazing sun and
rising temperatures. As they pass the 1.5 mile mark, Jamie takes a gullp of water and finishes up
her first bottle. This makes her
wonder, does she have enough water to keep drinking at that rate for the
remainder of the hike? Pike offers to help calculate our water consumption
rate in terms of ounces of water
per mile hike. We'll do this
calculation in PyTon using variables to help
us organize the data. First, let's create variables to store the number of miles
Jimmy has hiked so far, 1.5, and the number of ounces
of water she has drank. 12. Let's also create variables for the
length of the hike, 4.73 miles and for the volume of water she
has with her, 40 ounces. Using the first two
variable assignments, we can determine
the current rate at which Jamie is
drinking water. We must simply take the
ratio of the water she has consumed to the
distance she has hiked. To keep track of the result, let's assign it to the
variable current CR, which stands for current
consumption rate. Then let's calculate the
maximum consumption rate that Jamie can afford throughout the hike using the
last two variables. Let's store that information
in the variable MAX CR, which stands for maximum
consumption rate. By executing these cells, we find that Jamie's
current consumption rate is 8 ounces/mile, and the maximum
consumption rate she can afford is 8.46 ounces/mile. Of course, Pike gets
the same result, but Jamie is a bit confused by how he delivers the answer. Without context, it is difficult for Jamie to know what
these numbers mean. In PyTon an easy way
to provide context for a program's output
is to use strings. So let's create two new
string variables to contextualize Jamie's
current water consumption and maximum water consumption. Great. Now let's
see how we can use those strings jointly with the values to provide
some context. We may be tempted to concatenate the description text
and the output value. However, if we do that, we receive an error
message telling us that PyTon cannot concatenate
a string and a float. Well, if we think about it, we know that the plus operator
has a different meaning depending on whether it is used with numbers or with strings. When presented with both
a string and a number, Pyton is confused
about what to do. Thankfully, as we saw
in the previous video, it is possible to represent
numbers as strings. So if we knew how to convert current consumption rate from a numeric value to a string, we could perform
the concatenation. Let's see how to do
that. In programming, the operation of
converting a data type into another data type
is called typecasting. In particular, we
can use the built in function STR to convert or cast the variable
current consumption rate from a float to a string. That is, we can type STR and then enclose
our calculation in parentheses to perform the
numeric to string conversion. If we execute the cell, we see that the value
associated with the current consumption rate is now written between
single quotes, which means that we
have successfully converted the float to a string. With the value converted, you can see that the
concatenation now works. Similarly, we can apply the
string casting function to the maximum consumption
rate calculation and concatenate
it with max text. We now obtain a much
more informative output, as I'm sure you agree. Awesome. Jamie looks
to be on track with our water consumption and can continue drinking water
at her current rate. Converting numeric values such
as floats and integers to strings is one of many casting operations
we can perform in Piton. It is also the most straightforward casting
operation, since, as we have seen in
the previous video, any numeric value can be
represented as a string. But this begs the question,
can we do the opposite? Can we convert strings
into integers and floats? The answer here is
a bit more nuanced. When a number is
represented as a string, the functions int and
float can be used to convert the string into an integer or a
float respectively. For example, using
the float function, we can cast the current
consumption rate and maximum consumption
rate variables from strings back to floats. Note that the single quotation marks around the values
have disappeared, indicating that the values
are numeric and not strings. But be careful. Not every string can be cast
into a float or an integer. For example, we cannot convert our entire current consumption
sentence into a float. That doesn't make sense. Finally, using the
float and in functions, it is also possible
to cast integers into floats and
floats into integers. For example, if we assign the float version of the current consumption
rate to its own variable, we can then use the int function to convert the value
into an integer. However, be mindful that when you cast the
flow to an integer, the decimal portion of
the number is lost. For example, casting total miles to an integer results
in the value four. We indeed lost the
decimal portion during the cast operation. Alright, I know this was
a lot of information. To help you remember,
we've prepared the following summary table
describing the casting rules. For your reference, this
table is reproduced at the beginning of the
exercise workbook that follows this video. Awesome. We now
know how to store and access information
using variables. Moreover, we've learned how
to manipulate data types. In the next video, we will practice using variables
and typecasting.
12. Variables - Exercise Solutions: In this workbook, you
got the chance to practice using variables
to solve problems. You also learned several
more concepts related to variables which make them even more of a useful
programming tool. Let's go through the solutions. First, in exercise one, we revisited a concept that was discussed in the previous
guided examples video. That is, Python
does not allow us to concatenate strings
and numeric data. In part A, we created two variables
to store the number of Blaze wins 13 and the
number of Titans wins 12. In Par B, we created two more variables to store
the description strings, Blaze wins and Titan wins. Then we cast both
numeric variables, Blaze wins and Titans wins to strings using the STR function. Doing so allows us to avoid an error and produces the
desired string output. In Part C, we introduce
the concept of F strings. F strings are great
for embedding variables into strings
more naturally than by using concatenation and casting numeric
values to strings. Here, we can either reuse the square text variables from Part B in our string like this, or we can directly type out
the score text like this. Next, in exercise two, we use the concept of
multiple assignments to create variables for each of the team's
scores and set them all to zero in a
single line of code. We can see from the
outputted value that both variables have indeed
been assigned the value zero. Moving to exercise three, we can take advantage of
the plus equals assignment operator
that Python provides to add values to existing
variables more efficiently. For each quarter,
we add the points scored to the corresponding
team's score variables. After a close game, the final
score of the Titans is 112, while the final score
of the Blaze is 108. It looks like the Titans
have won the championship. Finally, in exercise four, we encounter a custom
metric courtesy of your coworker
called player magic. We can determine
the final value of the player magic variable by calculating the variable
value after each line. After line one,
player magic is ten. In line two, we apply the
modulus assignment operator. This line of code is saying that player magic is now equal to the previous value of player
magic ten modulus two. Because two divides ten evenly, ten modulus two is zero. So after line two,
player magic is zero. On line three, we add 23 to the previous
player magic value, zero to get player magic as
equal to 23 after line three. Line four applies the
division assignment operator. This divides player magic, which is 23 by five to get 4.6. Then on line five, we apply the floor division
assignment operator, which removes the decimal
component from 4.6, leaving player magic equal to four at the end of line five. Online six, we multiply four by nine to get player
magic equal to 36. Line seven tells us we
need to subtract 34 from the previous player magic
value 36 to get two. Finally, on line eight, we apply the exponent
assignment operator to set player magic equal to two to
the power of three or eight. And it looks like Python
agrees with our assessment. Great. Now that you
are familiar with how variables work and how to use them in more
advanced contexts, we can move on to the next
topic, built in functions.
13. Built-in Functions: In previous videos,
we've used several of BTon's built in functions
to perform various tasks. While in those videos, we explain how to use a few
of the built in functions. We have postponed a
rigorous discussion of this concept until now. So let's dig deeper together
into this important notion. In PTN, built in functions
are predefined shortcuts that allow programmers
to perform specific tasks with
minimal effort. These functions accept
certain inputs known as arguments on which they
perform some operations. Once the operations
are performed, a function typically
produces an output, which is referred to
as the return value. Take our previous usage of the type function as an example. We gave the function
the variable total miles as an argument, and it returned the
variable type float. Note that the process by
which the function type gets from total miles to float
is not explicitly given. In a way, you can
think of a built in function as a
little black box. A black box? That doesn't
sound like a good thing. Well, it turns out that it's actually a very useful feature
of built in functions. Because we can use built in functions without learning
their inner workings, we can save time
and effort making our programming tasks easier
and quicker to complete. As you can see, built in functions are very
helpful in PyTN. In the next video, we'll expand our coding toolkit
by introducing a few new built in function and exploring use cases together.
I'll see you there.
14. Built-in Functions - Guided Examples: Jamie and Pike have reached the second major
obstacle of their hike, a daunting uphill stretch that even experienced
hikers find difficult. While taking a break from
the challenging ascent, Jamie wonders what
total elevation change she'll experience
during the hike. Pike reminds her that the
elevation gain is 500 feet, and of course, the elevation
loss is also 500 feet. To find the total
elevation change, we must add the
elevation gain and the absolute value of
the elevation loss. In Pyton the ABS function has been designed
to do just that. Adding the absolute value of elevation loss to
elevation gain, we find a total
elevation change of 1,000 feet as you
probably expected. And that's also the
number that Pike reports. But again, Jamie would like a bit more context
around the output. In a previous video, we added context to our
output by casting numerical results to string and concatenating a
descriptive label. This worked, but there is
a better way to do it. In PyTon, the print built in function makes it easy to display values in
the output box. The key advantage of the
print function is that it handles typecasting and
concatenation for us. Let's see how to
use this function. For convenience,
let's first assign the result of our
calculation to a variable. Then let's create a label
variable and assign it to string total elevation
change. All right. We are now ready to call
the print function. This function has an
interesting feature that we have not seen yet. It can handle
multiple arguments. To input multiple
arguments in a function, we write them between the parentheses and
separate them with a comma. When we execute the cell, the print function writes to the output box the value
of its first argument, followed by the value
of its second argument. We should know that the
order of the inputs matters. If we flip the order
in the function call, we also flip the display
order in the output box. Great. Now, Jamie and Pike are all rested up and ready to
tackle the steep ascent. Before we follow
them, let's make a few final remarks about
built in functions. The print function
is just one of many built in functions
admitting multiple inputs. For example, we can
use the Max built in function to determine
the largest number out of the argument one, four, two, six, and
five as follows. For your information,
ITN has around 70 built in functions ready to assist you with
common operations. You'll get the chance to
explore a few more of those built in function in the
exercises that follow.
15. Built-in Functions - Exercise Solutions: In this workbook, you explored several of Python's
built in functions. Let's break down the solutions. In Exercise one, we can output Alex's workout plan
with the correct formatting by utilizing
the escape sequences, backslash N and backslash T to create new lines
and tabs respectively. After the header and
each day's workout, we insert a new line
character which tells Python to move the following
text onto the next line. We also add the tab
escape sequenced before each day's workout line to tell Python to indent
the following text. Our result is a well
formatted workout plan. Next, in exercise two, we can determine the absolute value of the difference between today's and yesterday's
step counts by using the ABS function. Because we are finding
the absolute difference, the order in which we subtract the two step values makes no difference to
our final result. We find that the
difference between the two days step counts is
3,050 in either arrangement. In exercise three, we can
use the max function to identify the most number of steps Alex took in
the last seven days. By passing the seven step counts as arguments to
the MAX function, we obtain the greatest number of steps Alex took was 15,400. Then to solve exercise four, we invoke the Min function to find Alex's fastest
hundred meter time. Similar to how we use
the Max function, we pass the five times
in as arguments and get that 13.87 was
Alex's fastest time. Finally, in Exercise five, we calculate the average
minutes that Alex plans to exercise per day using the
standard average calculation. Then we pass our average
minutes variable along with one as arguments
to the round function. This tells Python
that we would like average minutes to be rounded
to the first decimal place. Awesome. Now you have
gotten the chance to use several Python's
built in functions. In the next several videos, we will be exploring
some more built in operations that
Python provides.
16. Built-in Type Methods: When Pike reported the
total elevation change in a previous video, he overlooked capitalizing the first letter of the output. Capitalizing the first letter of a string is a
fundamental operation. So, surely, PyTon must provide a capitalized built in function to help
us fix this issue. Hmm. It looks like the capitalized function
does not exist. How strange? Well, the capitalized
operation is, in fact, available in PyTN, but it is not implemented as
a built in function. Instead, the capitalized
operation is implemented as a
built in type method. In this video, we'll show how to use built in type
methods to perform common operations and clarify the distinctions
between type methods and built in functions. Much like built in functions, type methods or tools that allow programmers to perform
common tasks quickly. Yet there are subtle differences
between the two notions, built in functions
or versatile tools designed to operate on
various data types. They provide programmers
with a flexible toolkit. In contrast, built
in type methods are specialized tools designed to work on a specific data type. They provide programmers with
a type tailored toolkit. For example, capitalizing
the first letter of a value makes sense if
that value is a string, but it doesn't really make sense if that value is a number. For that reason, the capitalized
operation is found under the umbrella of string methods instead of built in functions. Let's now see how to access the capitalized operation and use it on the label variable. To call a type method
on a variable, we must follow the
variable name with a dot. At that point, no pun intended. Most programming
environments will present you with a list
of available methods. That is a list of operations that can be
performed on the variable. Let's scroll through
the list and see if we can identify a good
candidate for our purpose. Oh, would you look at that? A method called
capitalize is available. That's promising. Et's
select that method. Before we execute the cell, we must append a pair of empty parentheses at the
end of the method's name. We'll say more about that
in the exercise video. When we execute the cell, we can see that the
method return or label string with the
first letter capitalized. Note that applying the
capitalized method to the label variable did not
change the value of the label. Instead, it created a copy of the original variable with
a capitalized first letter. To modify the content
of the label variable, we must reassign the
capitalized string. In line with our
previous discussion, note that the capitalized method can only be applied to strings. For example, if we try to apply this method to
the variable result, we get an error message. Other data types, such
as integers and floats, also have their
associated methods. We'll explore some of
them in the exercises. Now, I'll admit that
the difference between built in functions and type
methods is somewhat subtle. To clarify the distinction, let's consider the following
real life analogy. Imagine you're at the
grocery store to pick up some coffee
beans and oranges. Every item in the store, including oranges
and coffee beans, can be added to your card and purchased at the
checkout counter. In that sense, the operations of adding
items to your card and checking out mirror the concept of built in
functions in programming. They are generic operations that work on many
types of items. However, once you're home, the way you prepare your food will depend on the items type. For example, you might want to grind your coffee beans and
brew them in hot water, and you might want to peel your oranges and press
them into juice. These actions are tailored to the specific items
and therefore, resemble type methods
in programming. Just as it doesn't
make sense to try brewing oranges or
peeling coffee beans, type methods are
specialized operations that don't universally apply
across different data types. Great. We now have a better
understanding of built in type methods and how they are distinct from
built in functions. In the next video, we'll
explore a few additional built in type methods and see how they can help us manipulate data.
17. Built-in Type Methods - Guided Examples: Jimmy and Pike just completed
their steep ascent. The two hikers continue on
the trail at a good pace, but it's getting
even warmer outside. Jamie is curious to know what the feels like temperature is. Using his sensors to measure
the temperature, wind, and humidity, Pike calculates
the feels like temperature. Pike has now learned
that Jim would like some context around the
output of his calculations. But because he is unsure of how Jimi wants the
result formatted, he outputs the information with random capitalization. Oh, Pike. Unsatisfied with the format, Jamie asks Pike to show
her a few options. The first option
Pike proposes is to swap the case of all the
characters in his output. In Python, this can be done
using the swap case method. Unfortunately, the new format is just as hard to read
as the original one. Pike gives it another try and converts all the
characters to uppercase. In our code, we can do this
using the method upper. Converting to all
caps can be useful to emphasize important messages or to create case uniformity. But Jamie thinks
it's a bit rude. Pike is not giving up. I tries again by converting all the characters to lowercase. In PyTon, the lower
string method converts strings to lowercase. Like the upper method, the lowercase method can be used to create case uniformity. This output is clearly
more readable, but it still lacks
proper capitalization. Persistent Pike tries again and convert it output to title case. We can convert strings
to title case as well, using the provided
title string method. Title case can be useful when formatting a string for
a heading or a title. This output is much more readable but isn't
quite satisfying. Pike, you're so close. With one more trick
up is robotic sleeve. Pike modifies it output
formatting to be a normal sentence capitalization using the capitalize method. Great. Jamie is happy
with the new formatting. No need to be fancy. Pike takes note of following
this style in the future. Awesome. We have now seen several useful built in
string methods in action. In the next video, you'll get the chance to
practice using built in functions and built in type methods to operate on data.
18. Built-in Type Methods - Exercise Solutions: In this workbook, you saw how to use several more string methods. Let's discuss the solutions. To solve exercise one, we need to use the count method. If we call the count
method on code one and pass the string
ocean in as an argument, we can see that the word ocean occurs 14 times
within the message. To solve exercise
two, we can use the strip family of methods to remove the
distraction characters. You can either apply the
strip method repeatedly, or you can be a bit
more precise and use the Strip and R
strip methods where the distraction
characters appear only on one side of the string. Let's focus on this
more precise solution. First, we must strip the extra spaces from
both ends of code two. We can use the strip method with no arguments
to accomplish this. Second, we can remove the apostrophe characters
from the front of the string by passing the apostrophe into
the Strip method. Likewise, we can also remove the exclamation mark
characters from the front of the string by passing in the exclamation mark as an
argument to the Strip method. Then we can pass nine into the R Strip method to remove the nines from
the end of the string. Finally, we can
call R Strip with no arguments to remove the spaces at the
end of the string. Great. We are then left with
the string Apple Grove. Note that the order in which these methods are
applied is important, since strip will only remove the characters at the beginning
or the end of the string. It will not remove characters
in any other location. Moving to exercise three, we need to use the replace method. Using method chaining,
we can replace the zeros and ones in code
three with the empty string. Then we can replace
the twos with D, the threes with B,
the fours with L, the fives with A,
the sixes with M, the sevens with R,
the eights with Y, and the nines with I. This allows us to decode the message to get
the word library. Then to solve exercise four, we can use the find method
with the string library as an argument to find
the location in code one where the word
library starts. We obtain that library
starts at character 1,114. Finally, in Exercise five, we introduced the
concept of Booleans as values that can be
either true or false. Strings and numeric values have methods that
return booleans. These methods allow us to ask
questions about our data. For example, we can
determine if code four is alphanumeric by calling
the I lnum method. Here, we find that the code
is indeed alphanumeric. Awesome. Over the
last two workbooks, you have learned how to
identify functions and methods that you can use
to solve a given problem. This is a useful skill
that you will draw upon going forward in
your programming journey. In the next few videos, we will dive into
the Boolean type that we saw in Exercise five and learn how this type opens up a new class of problems
for us to solve.
19. Booleans and Comparison Operators: In the previous
exercise workbook, we use the method is digit. We noticed that this method
returned the value true, which is of the Boolean
datatype in this video. We'll explore this new data
type in greater details. Booleans are a
datatype that can only take the values true or false. At first glance, a
datatype that can only take one of two values
may seem of limited use. But it is, in fact, this very limitation that makes booleans so powerful.
Let's see why. By analogy, Booleans mirror the possible states
of a light switch, either on, true or off, false. In practice, Booleans are useful when we want PyTon to
answer yes or no questions. For instance, imagine you have difficulty with
numbers and require PyTn's assistance
to determine if 40 degrees Fahrenheit is
above the freezing point, which is 32 degrees. We can ask PyTon this question using a comparison expression. Comparison expression tests
whether two values satisfy a certain relationship
and returns the value true if the relationship is satisfied and false
if it is not. For instance, to determine if 40 degrees is above freezing, we can use the greater
than comparison operator. When PyTon evaluates
the statement, it returns the
Boolean value true, indicating that 40 is
indeed greater than 32. You are learning a lot today. Conversely, if we use the less than operator
in the statement, PyTN evaluates it to false. We can similarly test weak
inequality relationships using the greater or equal operator and the less than
or equal operator. Beyond numerical values,
Python comparison expressions can also be used to compare
strings and other data types. For example, let's assign the string Tuesday to
the variable day one, and the string Monday to
the variable day two. Now, let's say we want to test whether these two
strings are the same. Can we use the equal sign as a comparison operator?
Of course not. Remember, the equal sign is the assignment
operator in Pyton. Evaluating this
expression reassigns the string Monday to
the variable day one, which wasn't our
original intention. To create an equality
comparison expression, we must instead use the
double equal operator. Since the strings Monday
and Tuesday differ, evaluating the expression
returns the value false. Finally, if we instead want to test if two values
are different, we use the inequality operator
exclamation point equal. Replacing the first
equal sign with an exclamation mark and
evaluating the expression, we obtain the value true, indicating that the two
strings are indeed different. Great. We have covered yet another PyTN
data type, Booleans. In particular, we have seen
that Booleans are very useful to ask yes or no questions
within the PTN program. In the next video, we will
build upon this foundation and see how we can ask more
complex questions in PTN.
20. Booleans and Comparison Operators - Guided Examples: Trekking along the
roller coaster trail, Jamie and Pike have just
hit the two mile mark. Full of energy, Jamie wonders whether they
can pick up the pace. To do so, Pike would need at least 73% of his battery left to boost up to turbo speed. Jamie, on her side, would feel comfortable
hiking faster, knowing that a few clouds are in the forecast to block
out the intense sun. In essence, Jamie and Pike want to answer the following
yes or no questions. Is Pike's battery level
greater than 73%? And is the weather
forecast cloudy? They can't hike faster unless the answer to both
questions is yes. Let's see how we
can ask PTN whether these two conditions are
simultaneously satisfied. Conveniently, PTN
provides the keyword to help us perform that test. The end logical operator, when placed between
two boolean values, allows us to check if the two values are
simultaneously true. If the two values are true, the entire logical expression
evaluates to true. On the other hand, if at least
one of the value is false, the logical expression
evaluates to false. Pike calculates that
he has 65% battery remaining and predicts that some clouds will show up during the remainder
of the hike. Let's use that
information to figure out if going faster
is an option. We'll begin by creating
two variables to represent Pike's battery
level and weather forecast. Then we can ask whether
Pike's battery level is at least 73% and whether the weather forecast
is cloudy as follows. Executing the cell,
we obtain false. Of course we do. The first Bolling expression
is clearly false. That's a bummer. Jamie and Pike will not be able to
hike any faster. But wait. Jamie
has another idea. When they venture out
in the wilderness, Pike usually brings
some backup power. Jamie asks Pike if he brought either a portable battery
or his mini Winterbine. Having either the battery or the win turbine would be sufficient to give
Pike some more charge. In this situation, Jamie
wants to answer the question. Did Pike bring either
the portable battery or the mini win turbine? To ask questions like this, Biton provides another
logical operator, the operator or when placed
between two booleans, the or operator verifies
if either value is true. If at least one of
the values is true, the entire logical expression
evaluates to true. Only when both boolean
values are false, does the logical expression
evaluates to false. Pike scans his
internal inventory and informs Jamie that he brought
his mini wind turbine, but not a portable battery. We can use this information to set up another
logical expression. Let's first create
two boolean variables to indicate that Pike
brought the mini turbine, but not the portable battery. Then we can perform the
test by simply writing has mini turbine or
has portable battery. Note that there is no need
for comparison expressions here because our two variables
are already booleans. Executing the cell,
our logical expression evaluates to true. Again, this is what we expected
because at least one of our two variables
is true. Awesome. Pike can now attach the turbine
to harness the power of the wind and charges battery
a few extra percent. Then Jamie and Pike
will be able to continue their hike at
an even faster pace. Great. You now know how
to use comparison and logical operators to ask yes or no questions within
the PTN program. It's now time to
practice this new skill.
21. Booleans and Comparison Operators - Exercise Solutions: In this workbook, you got
some more experience with the Boolean type and comparison
and logical operators. Let's go through the exercises. In exercise one, you built some more complex
comparison statements. To solve part A, we
need to calculate the average temperatures early in the week and
late in the week. We can store those values in variables and then
use the greater than operator to test whether
it is the case that the early temperatures were greater than the
later temperatures. The comparison results in false, which means the average
temperature earlier in the week is less than the average
temperature later in the week. In Part B, we need to determine if the absolute
temperature change between Monday and Tuesday
is at least as large as the absolute
temperature change between Thursday and Friday. We can use the ABS function to calculate the
absolute differences. Then we can use the greater
than or equal operator to identify whether the
absolute difference between Monday and
Tuesday is at least as large as the absolute difference between Thursday and Friday. We find that the comparison
results in true, which means the
temperature changed more between Monday and Tuesday than it did between
Thursday and Friday. Moving to exercise two, we can check whether the
temperature is strictly increasing from Monday to Thursday using multiple
less than operators. This statement is asking
three questions in one. It asks whether
Monday's temperature is less than Tuesdays, whether Tuesday's
temperature is less than Wednesdays and whether Wednesday's temperature
is less than Thursdays. Our statement evaluates to true, indicating that these
four temperature values are strictly increasing. In exercise three, we
introduced the knot operator. We can use the operator to solve this problem in
two different ways. First, the more intuitive
approach is to directly negate both the will rain and temperature
will drop variables. However, it is logically
equivalent to check if will rain or temp will drop are true and then
negate the group. This works because
of De Morgan's law, which says that not A and not B is the same as not A or B. In both expressions,
temp greater than or equal to 90
will evalue it to true. Then in the first expression, both not will reign and not temp will drop,
evalue it to true. Three trues linked with and
operators results in true. In the second expression, will reign and temp will
drop are false, and they are linked
with an or operator. So this expression will
evalue it to false. But we apply then operator, which turns the
false into a true. Then we are evaluating true
and true, which is true. Next, in exercise four. When tackling complex comparison
and logical expressions, it is best to break them
down into smaller parts. We can do that here by first accounting for the fact that it should not be hailing. Then we see the
word and so we know the remainder of the expression will be joined with
an and keyword. Also, because of the phrase, one of the following
conditions must be true, we know that these
two conditions will be joined with
an or operator. Next, we can translate at least 500 yards
of visibility and a precipitation rate
of no more than 0.2 "/hour into this statement. And we can translate no less than 600 yards
of visibility and a precipitation rate
of no more than 0.3 "/hour into this statement. Given our input variables, this part of the expression
evaluates to true. This part of the expression
evaluates to false, and this part also
evaluates to false. These two expressions
are linked with an or, so false or false is false. As a result, we are left with true and false, which is false. Finally, moving
to exercise five. In part A, we create four variables and set them
equal to placeholder values. Then in Part B, we use these variables to
set up an expression to determine whether there is
an increased avalanche risk. Because we need to know if one of these conditions is true, we will use an or
operator to link them. We can check if there has
been more than 12 " of recent snowfall and if there are three or
more weak layers. And we can also check if the wind speed is greater
than 20 miles per hour, and there has been a
large temperature change. Finally, in Part C, we can replace the placeholder
values of our variables and evaluate the
expression to get that there is not an increased
risk of avalanches. Great. Now that
you have practiced creating comparison and
logical expressions, we are ready to move on to
our next topic, conditionals. Booleans and logical expressions are an important part
of conditionals, so you will have
the opportunity to practice them even
more in the future.
22. Conditionals: In the previous videos, we explored how to answer
yes or no questions and PTN using comparison and
logical expressions. In this video, we
will study how to use these expressions to control the execution flow of our code. All of the PTN programs we have written so far run linearly, moving from one line to the very next until the end
of the program. By analogy, the execution
of our code has been like a smooth drive on
a straight highway leading directly to
our destination. But in programming,
as in driving, the path we want to follow
isn't always straightforward. Just as you might
need to detour to a rest area if your
car is low on gas, programmers often
need to control the execution flow of their code based on
certain conditions. For example, suppose
you are designing a simple driving
assistant program that alerts drivers
when it's time to fuel. The program must
work as follows. If a car passes by a rest area when it has less
than one fourth of a tank, the program must output the
string time to fuel, baby. In programming, conditional
execution decisions like that can be implemented
with I statements. And if statement begins
with the keyword, I followed by the condition
we want to test and a column. Note that when pressing Enter after writing
the terminal column, the next line of code becomes
automatically indented. This is not a glitch. The indentation signals to Python that the code
we write on this line must be executed only if the comparison
expression is true. If the comparison
expression is false, the indented line of code
will be skipped at execution. We can easily verify that our program performs
as intended. If we assign the value 0.1 to the variable gas remaining
and execute the code, the desired string is printed. And if we assign the value 0.5, nothing appears in
the output box. Now, a program that returns
nothing is a bit unsettling. It makes it hard to tell whether or not the program
has been executed. Let's improve our code
by having the program output the string continue
straight at the very end. This string should
be printed whether or not the comparison
expression is true. This can be done in
PyTon by writing an unindented print statement
under the current line. Testing our code
with the value 0.1, we observe that both print
statements are executed. And changing 0.1 to 0.5, only the final print
statement gets executed. As you can see, proper
indentation is key when working with if statements because it determines the scope
of the statement. If statements are powerful, but they are just one
building block that Python provides us to control
the flow of our code. Piton also provides
more building blocks to handle more
complex scenarios. For example, imagine you are approaching a T intersection
and must decide based on the amount of
gas remaining whether to take the short path
or the scenic route. If you have more
than half a tank, you can take the scenic route. If not, you must take
the shorter path, otherwise, you would
run out of gas. This scenario differs from
the previous one because here we must choose
between left or right. We can't skip this choice altogether and
continue straight. To help drivers make
such a decision, let's create a second version of a driver assistance program. This new version
will still execute a specific piece of code
when the condition is true. But then if this
condition is false, we want our code to execute
a different piece of code. To achieve that, we write
the Ls keyword followed by a column on the same
indentation level as the I statement. Under the statement, we write on an indented
line of code, the piece of code that we want executed if the
condition is false. Finally, for the sake
of completeness, let's write an unindented
line of code that will be executed regardless
of the chosen path. Let's now test if our
code work as expected. If we set the variable
gas remaining to 0.7, the code associated with the
I statement is executed. And if we change the variable gas remaining
to a value of 0.3, the code associated with the
Ls statement is executed. Note that in both scenarios, the final print statement
is always executed since it is outside of the scope of the
conditional block. I and IL statements
are powerful concepts that enable programmers to control the execution
flow of their code. In particular, the IL
structure is very helpful for situations that involve two mutually exclusive
scenarios in the next video, we will generalize
this IL structure to accommodate situations
where there are two, three, four, or even
more possible scenarios.
23. Conditionals - Guided Examples: As Jamie and Pike
approach the summit, they reach a critical
junction where they must choose one of three paths. The appropriate path to follow depends on Jamie's energy level, which can either be
high, medium or low. If Jamie has high energy, they will be right extending their journey by an
additional 2.8 miles. If our energy is medium, they will continue straight, maintaining the original
high cland of 4.73 miles. Finally, if our energy is low, they will take a shortcut
by veering left, reducing the track by 0.56 mile. Let's use conditional statements to represent the
decision process. We'll build upon concepts we
are already familiar with. In the last video,
we learn how to direct or code down
two paths based on the value of a
logical expression using I and's statements. Well, it turns out that we can extend this
approach to guide the execution of our code down
three or even more paths. For example, we can implement the following logic to decide
which path Jamie must take. First, we test whether Jamie's energy level is
high with an I statement. If this condition is true, Jamie will take the path that
adds 2.8 miles to her hike. But if this condition is false, we must determine whether her energy level
is medium or low. This can be done by
embedding another Is block in the first s block to test if our energy
level is medium. If the condition is true, Jamie will follow the
route originally planned. But if this condition is false, we can infer that
Jamie's energy level is low and she should
take the shortcut. As this example illustrates, we can represent
multiple choices by nesting if else blocks. While this approach works reasonably well for
three alternatives, it quickly becomes burdensome when there are more
possibilities. You'll get to
experience just how conversome it becomes
in the exercises. Thankfully, there's
a better way. To simplify programmers lives, PyTon provides the keyword LIF, which stands for s if. The code in the ALIF
block is executed if and only if the expression of
the if statement is false, and the expression of the
ALF statement is true. In practice, ALIF
statements can be used to implement the same logic
as nested ifelse blocks, but they are much
easier to read. By following the logic, Pie can determine
which path to follow. Let's implement that
logic in Python. First, we'll test if JB's energy level is high
with an if statement. If that's the case, we first update the hiking
distance accordingly. And output the path to follow. Note that conditional statements may include multiple
lines of code. Indentation determines
whether a line of code is part
of the statement. We follow the I statement with an IF statement to test if Jamie's energy
level is medium. Since we do not need to
update the hiking distance, in that case, there is no need to reassign the
variable total miles. We complete our conditional
block with an L statement to handle the case in which
Jamie's energy level is low. In that case, we must decrease the value of total
miles by 0.56. Finally, let's write an
unindented print statement to output the
updated total miles. Because this last line
of code is not part of the If conditional block, it will be executed every
time we run the program. Upon Pike's inquiry, Jamie concedes having a
medium energy level. Let's assign the variable
energy level accordingly. Then executing the cell, our program recommends
sticking to the original plan. Awesome. Jamie and Pike will
then continue on their original path
up to the summit. We'll leave Jamie
and Pike complete this hike and catch up with
them once they return home. Awesome. We now
understand how to use conditional
statements to control the execution flow of our code. In the next workbook, you'll have the
chance to practice using conditional statements.
24. Conditionals - Exercise Solutions: In this workbook,
you practice using conditionals in several
different circumstances. Let's discuss the solutions. In exercise one,
you experienced how the F block can make your
code easier to read. In Part A, we can nest
if and else Block to update the hours to explore variable based on the
environment condition. While these two code blocks
are logically equivalent, it is best practice to explicitly test for
all of our conditions. Leaving the success state to be handled by the else block can cause unexpected behavior if your program receives
erroneous inputs. In Part B, we can use the LF keyword instead of
nesting if else blocks. This makes our code cleaner while being logically
equivalent. In exercise two, you saw two scenarios in which nesting conditional blocks
might be the better option. In part A, we want
to nest conditionals because each check is a
prerequisite for the next check. First, we ask whether
the field check passes. If it does, then we can check
if the crew check passes. If it does, then we can do
our final navigation check. If that check passes, then we print the launch
ready message. If any of those checks fail, we print a specific
error message to indicate exactly
which check failed. Moving to Part B, we encounter another situation in which nesting conditionals
is the best option. Here, we want to
nest conditionals because we need to verify
that the Zeus rocket is both available and operational before we continue checking the other conditions. We can check those
other conditions using a nested I LFL block where each condition checks whether
the mission type matches the crew available and
fails if there is no match. To solve exercise
three, we need to be mindful of the order in which
we check our conditions. We need to first check whether
the engine temperature is greater than 90 so that we can output the correct message. If instead, we first check whether the engine temperature
is greater than 50, all temperatures that
meet that condition, including temperatures
that meet other conditions will incorrectly cause the
caution message to be printed. As you can see, you need to be mindful of the order
in which you check your conditions to ensure that your code behaves as expected. Finally, in exercise four, we can utilize the
ternary operator to write a conditional
on a single line. We would like the status to be sufficient if food supply
is greater than 50. Otherwise, it should
be insufficient. Awesome. You now have
a solid understanding of conditionals and
conditional logic. In the next few videos, we will shift to exploring another useful data type, lists.
25. Lists: In the previous
video, we saw how to use strings to
represent data. In particular, we
consider the example of a shepherd spy
ingredients that we represented in one long string. While this method works, it's not the most
efficient way to access and manipulate
each ingredient. In this video, we'll
explore a better way to organize this type of
information using PyTon lists. Lists are versatile tools
that can store collections of items such as the
ingredients in a recipe. Lists allow us to
maintain order, access items easily, and perform many operations such as
adding and removing items. For example, we can represent the Shepherds By ingredients
as a list of strings. To create a list in Piton, we enclose its item within square brackets and separate
each item with a comma. Just like each character in a string has an
associated index. Each item in a list is also
associated with an index. For example, to retrieve
veggie brat from our list, we put brackets at the
end of the ingredients variable and include the corresponding
index for inside them. Now that you
understand the basics, let's make a few
more observations. First, lists in Piton can store anywhere from a few items
to several million of them. That is to say that lists
can be used to represent a few grocery items or to represent the inventory of
an entire grocery store. Second, lists are
incredibly versatile. They can hold strings, integers, floats, booleans, or a
combination of these. We can even create lists
that contain other lists. In our upcoming videos, we'll explore these
possibilities further. Moreover, we'll
dig in some of the built in methods
available for lists. As we explore these methods, you'll see firsthand why
lists are better than strings to organize
collections of related items.
26. Lists - Guided Examples: Jimmy and Pike are
back home after their exhilating adventure
on the roller coaster trail. Eager to embark on
another journey, Pike suggests planning
a more ambitious hike that involves navigating
between multiple waypoints. Jimmy agrees, but notes that this will require
careful preparation. The first step in
their planning process is to compile a
list of waypoints. Pike proposes an
adventurous route starting from Eagles
Crest Trailhead, leading to Crystal Brook Bend, descending into Echo Canyon, climbing out of misty falls and culminating with a steep
climb at Mount Silvercrest. Let's represent this list
of waypoints in Biton. Between square brackets, we write strings to
represent each of the five waypoints and separate
those strings with amas. Then we assign our
newly created list to the variable waypoints. To verify that our list
was created properly, let's visualize it. Great. According to Pike,
everything looks good, but that's when
Janie realizes that they forgot to specify their
route to get back home. Oops. Pikes suggest they
pass by Star Watch lookout, continue their trek
toward Jem Lake, and then return to
Eagles Crest Trailhead. To add these waypoints
to the list, PyTon provides us with
the method append, which takes the item to
append as an argument. Let's verify that the waypoints
have indeed been added. Wonderful. As you might
have anticipated, the items were
appended to the end of the list in the order in
which they were added. While him agrees with
Pike's suggestions, she also suggests they stop at Pipers Cove for the
scenic views before hiking to Jem lake. To add an item at a specific
position in a list, Piton provides us with
the insert method. This method takes two arguments. The first argument specifies the index where the
value must be inserted. The second argument specifies
the value to be inserted. When we execute the cell, we obtain an updated list where Piper's Cove has been
inserted before Gem lake. Seeing the full list
of destinations, Jamie feels they are
being overly ambitious. Consequently, Pike
proposes removing Crystal Brook Band from their itinerary since it's too far from the
other waypoints. To remove an item from the list, PyTon provides us with
the remove method. This method takes the item to
be removed as an argument. Oh, no. What happened? Why do we get an
error message here? Well, notice that we
did not capitalize Crystal Brook Ben in the same way as it
appears in the list. We have essentially
tried to remove an item that doesn't
exist in the list, and PyTon didn't like that. Correcting the capitalization, we remove the item successfully. Perfect. Jamie and Pike are now both satisfied
with the list. Curious, Jamie asks Pike how many waypoints they will
visit during their hike. To determine the number
of elements in the list, we can use a function
we are already familiar with the LN function. Eight waypoints to visit. This hike is going to be
lots of fun. Awesome. Now that we have seen several useful built in
methods for lists, it is time for you to practice. In the next video, you'll
have the chance to work on some exercises
on these concepts.
27. Lists - Exercise Solutions: In this workbook, you got to practice using lists to store, organize and operate on data. Let's break down the solutions. To solve exercise one, we can use the syntax and methods that we saw in
the previous videos. In Part A, we create the packing list by enclosing our data between
square brackets. In Part B, we can use
the append method to add toothbrush and phone
charger to our packing list. Then in Part C, to insert
book after sunglasses, we use the insert method. We pass in three, which tells Python to insert our
data at the third index, and we pass in book as the
data we would like to insert. Finally, for exercise
one, Part D, we can remove sunglasses by passing it in as an argument
to the remove method. Moving to exercise two, Part A, we can sort our packing list in alphabetical order using the
sorted built in function. Python also provides
the list method sort, which sorts elements of a
list in alphabetical order. Both the sorted function
and the SRT method, technically sort lists
in ascending order. For string data, like we have here, this means alphabetically. For numeric data, this just means from lowest
to highest value. Also note that the
sorted function does not modify
the original list, but the sort method does. Then in Part B, we can
sort our packing list in reverse alphabetical
order by first applying the sort method and then
the reverse method. But this is not the only way to reverse alphabetize a list. We can also apply
the sort method with the reverse
equals true argument. Or we can call the
sorted function and pass its result directly
into the reverse function. Just be aware that if you do not cast this
result to a list, you will end up with
this unhelpful output. Casting our result to a list, we now have our reverse
alphabetize packing list. In exercise three, we introduced the concept of
multidimensional lists. This can be a tricky concept
to wrap your head around, so don't be discouraged if these exercises seemed
a bit more difficult. In Part A, we can create a multidimensional list to store the expenses for
each city like this. The zeroth index of each
sub list stores the city, and the first index stores
the list of expenses. The zero value in this list is the expected
accommodations expense. The first value is the
expected food expense, and the second value is the
expected transport expense. In Part B, we can assign the correct values to
each variable as follows. To access London England
from our expenses list, we specify zero for
the zeroth sub list, and then zero again for the
zeroth element in that list. This same logic applies for
the other city strings. Then to access the accommodations
expense for Paris, we can specify one
to get this list, one again to get this list, and then zero to retrieve
the zeroth element. For the Paris food
and travel expenses, we simply modify the third index to retrieve the correct value. Next, to access the accommodations
expense for London, we specify the indexes
zero, one, and zero. To access the food
expense for Venice, we specify 31 and one. And for the Munich
travel expense, we specify 21 and two. In Part C, we can
utilize the sum, Min and MX functions to
answer our three questions. We pass the first index in the zeroth list into
the sum function, which then returns the
sum of the list items. Then to find the least amount
we expect to spend on food, we can use the Min function. We pass in the first index of the first element in
each of the city lists, and the Min function
finds the smallest one. To answer the third
question, we can pass the expenses list for Venice
into the MAX function. Moving to exercise four, Part A, we can create three
lists, destinations, distances, and times using
the normal List syntax. In Part B, we use the
zip function and cast our result to a list to group the data at each index together. Our result is a list
of tuples where all the data relating to
Paris is at the zeroth index. The data relating to Munich
is at the first index, and the data relating to
Venice is at the second index. Great. Now you have gotten to practice using and
operating on lists, and you got to learn a few new
concepts related to lists, which make them
even more useful. In the next video,
we will dive into tuples and learn how
they are distinct from
28. Tuples: In the previous
exercise workbook, we use the zip
function to combine related elements from
three different lists into a single list. We noticed that the element of that single list are
so called tuples. Hm. In this video, we study these tuples in greater detail and explore
how they are similar, yet different from lists. Similar to lists, tuples
are collections of items. But to create a tuple, we enclose the items
of a collection within parentheses instead
of square brackets. Like lists, tuples
also support indexing. Individual items and slices of items can be accessed
using standard syntax. The differences
between tuples and lists become apparent
when we start using them. As we demonstrated
in previous videos, once a list is created, it can be modified
with methods such as append, insert and remove. In contrast to lists, tuples cannot be modified
once they are created. Accordingly, there
are no append, insert or remove methods
associated with tuples. Moreover, the few methods available do not perform
modifications on tuples. In other words, the big
difference between lists and tuples is that lists are
modifiable after creation, and topples are not. Being unable to modify a collection is a
significant limitation. So why would someone
ever want to use a tuple instead of a
more flexible list? Well, precisely because
tuples are unmodifiable. They are a valuable
tool for organizing data that needs to stay
consistent throughout a program. For example, the road
trip stop tuple that we defined earlier contains
information that is definitive. The distance between
London and Paris is set in stone and
should not be changed. Any modification to this
value would be a mistake. As another example,
geographic coordinates are also a type of data that we may want
to store in a tupple. The latitude and longitude of New York City
will never change. Using a tuple guarantees
that we won't accidentally modify those values at some point in a program. Great. We now understand what topples are and how
they differ from list. Although topples are less
frequently used than list, they are ideal for storing information that must
remain unchanged. In the next video, we'll explore another valuable yet
less common data type to store collections, sets.
29. Sets: In the last few videos, we saw how to represent
collections of items using lists and tuples. In this video, we introduce a third and final data type used to represent
collections of items, sets. Sets are used less
frequently than lists. Nonetheless, we will
see that there are a few situations where
sets are preferable. Sets, like lists and tuples
are collections of items. In Python, we create a set by enumerating its item in
between curly brackets. Beyond this
difference in syntax, there are two main
distinctions between sets and the other
types of collections. First, while lists and tuples may contain
duplicate items, the items of a set are unique. For example, we may
represent the single banana, three oranges, and two apples that compose a fruit
bowl using a list. But if we instead represent the same collection of
fruits using a set, the duplicate items are removed, and we are left
with a collection of three distinct fruits. This property of sets is
helpful in practice when we want to obtain the unique
values of an existing list. For example, suppose we have this list containing
duplicate values. We can quickly obtain the unique values of
the list by casting it to a set using the
set casting function. The second big
difference between sets and the other
types of collections is that a set does not assign a specific position
to its items. In other words, the
items in sets are not associated with an index value specifying their position
in the collection. In programming,
when the items of a collection are assigned
a specific position, we say that the
collection is ordered. On the other hand,
when the items of a collection have
no specific positions, we say that the
collection is unordered. Finally, there is an
additional distinction between sets and tuples. Like lists, sets are modifiable. To illustrate, let's
know that we can add a new item to a set
using the add method. As you can see, apricot
has been added to the set. Note that the existing items
have changed positions, consistent with the
observation that sets are not ordered. Sets are great for
representing data when the existence of an item is more significant
than its position. Awesome. We have now seen three distinct data types to represent
collections of items. Each type has strands and
limitations that make it more or less suitable
depending on the use case. Lists are the most popular
tool to represent collections. They are modifiable
after creation, allow duplicates
and are ordered. Tuples and sets are less common, but they are useful in
specific situations. Tuples are not modifiable, allow duplicates
and are ordered. They are great for storing data that should not change
during a program. Finally, sets are modifiable, but do not allow duplicates
and are not ordered. This means that sets are
most useful when we want to ensure that our collection
contains unique items. In the next video, we will
explore a few scenarios where tuples and sets are preferable to list.
I'll see you there.
30. Collections - Guided Examples: At the trailhead
of Eagles Crest, Jamie takes a deep
breath of the crisp, fresh air and
embarks on her hike. Excited to immerse
herself in nature, Jamie proposes to keep an inventory of all the
wildlife they encounter. Always eager to assist Pike volunteers to
document their findings. Shortly after departing from
Eagles Crest Trailhead, Jamie and Pike's journey
gets exciting as they spot two deers and a
rabbit froliing nearby. As they meander between Echo
Canyon and Misty falls, Jamie notices another deer and a majestic elk amidst
the dense foliage. On their way to Mount
Silvercrest Summit, Pike spots a pair of mountain
goats skillfully navigating the rocky cliffs and three more elk grazing
in the distance. Approaching Star Watch Lookout, they witness a bear lumbering along the far
side of the riverbank. Finally, as they head back to Eagles crest Trailhead
to wrap up their hike, Jamie excitedly points out a pair of moose by
the water's edge. They perfect finally to their wildlife rich
expedition. Awesome. We'll now use Python to document the collection
of wildlife sightings. Out of the three types of collections we are
familiar with, which do you think is best to represent that
type of information? As you can see, this collection
contains duplicate values because Jamie and Pike recorded multiple sightings
of the same species. As a result, if we were to represent the
collection using a set, we would lose some
information as the duplicate values
would be eliminated. Moreover, because Jamie and Pike have already
completed their hike, we know that they will not add more animals to this collection. The collection is set in stone. For those reasons, using a
tupple seems appropriate here. Remember, the difference
between lists and tupples is that tuples cannot
be modified after creation. Once they have returned home, Jamie asks Pike to report the unique species they
encountered on the trail. To obtain this information, we can cast the wildlife
tuple into a set. Doing so transforms a copy of the wildlife tuple into a set removing the
duplicate values. Pike informs Jamie that they
have encountered bears, deer, elk, moose, mountain
goats, and rabbits. That's great. Jamie
is thrilled to have seen so many
species of wildlife. She wonders how
many more animals they could potentially
have seen. Specifically, Jamie wants to know which of the animals that live in our area they have not encountered during the hike. To help Jamie, Bike consults an old local wildlife
guide and finds the collection of all
animals inhabiting the area. Let's represent that collection
of animals using a set. Great. Now, to answer
Jamie's question, we must determine which animals are in the possible
wildlife set, but not in the wildlife set. In PyTon, this can be done by calling the difference method on the possible wildlife set and passing the variable
wildlife as an argument. As the name suggests,
the difference method returns a set containing elements that are
in the calling set, but not in the set
passed as an argument. Executing the cell
reveals a set containing three animals that Jamie and Pike did not see but
could have seen. When Pike informs Jamie
that they could have seen bighorn sheep,
bison, and eagles, Jamie indeed recalls
seeing some of these animals on
their first hike in the area several months ago. She asks Pike to
help her remember exactly which of
these three animals she has seen on
their first hike. Thankfully, Pike is a
reliable record keeper and save that collection
on his hard drive. Assigning the wildlife scene on the first hike into a set, we can use another method to determine which items
occur in both sets. To do that in PTN, we can call the
intersection set method on the first wildlife set and pass in the not seen wildlife
set as an argument. The intersection method returns a set containing the elements that are in the calling set, and in the set passed
as an argument. Executing the cell, we obtain
bighorn sheep and Bison. This means that
Jamie and Pike saw bighorn sheep and Bison
on their first hike, but not on their second hike. Great. Over the last
several videos, we have seen when to use lists, touples and sets depending
on our programming needs. In the following exercises, you'll get to practice how to use all three of
these data types.
31. Collections - Exercise Solutions: In this workbook, you had
the opportunity to practice choosing the correct collection
type for a given context. Additionally, you used each type specific operations
to solve problems. Let's discuss the solutions. In Exercise one, Part A, we are tasked with choosing a data type to store the
new book information. We know this information will
not change in the future, and that the order in which the information is
presented is significant. Therefore, we should represent the new book information
with a tuple. In Part B, we were introduced to the
concept of unpacking. We can unpack our new book
tuple into three variables, title, author, and
year, like this. Moving to exercise two, P A, we now need to
represent the genres of the checked out books. See that this collection of genres contains
duplicate values, which rules out using sets. We also know that this
data will be updated in the future when books are
checked out or checked back in, which rules out using tuples. So in this scenario, it
is best to use a list. In Part B, two
science fiction books and a mystery book
were just returned, and three biographies,
two poetry books, and a fantasy book
were just checked out. We can update the checked
out genres list accordingly, using the remove
and append methods. Then in Part C, we can count the number of
fantasy and poetry books that are checked out
using the count method. We obtain that there
are two fantasy books and two poetry books that
are currently checked out. Finally, in exercise three, P A, the librarian would
like a collection of the unique genres that are
currently checked out. Because we are looking for the unique genres, we
need to use a set. We can create a set from the
checked out genres list from exercise two with a
set casting function. In Part B, we use curly brackets to create a set with the genres of books that are
not checked out. Then in Part C, we can use set operations
to ask questions about the checked out genres
and available genre sets. First, we can use the union set method to get
all of the genres across the two sets and use the n function to
count 11 total genres. Second, we can determine
which genres are both checked out and available with the intersection
set method. Remember, the
intersection of two sets are the elements that
occur in both sets. We obtain that the biography, fantasy and poetry genres are both checked out
and still available. Third, we can find
which genres are available but not checked out
with the difference method. Because we wish to
find the genres that are in the
available genre set, but not the checked
out genre set, we must call the
difference method on the available genre set and pass in the checked out
genres as an argument. If we call the
difference method on checked out genres and pass in available genres as
an argument instead, we will get those genres which are checked out
but not available, which is the opposite
of what we want. Finally, for question four, we use the symmetric
difference set method to find those genres that occur in one set or the
other, but not both. We then apply the n function
to count that there are eight genres that are either
checked out or available. Great. Now that you
understand collections, we are ready to tackle one of the more difficult topics
in this course, loops. Loops are very useful for working with collections
because they allow us to efficiently
apply operations to every element
of a collection. In the next few videos, we
will break down loops into an approachable
concept and then learn how to use them in more
complex situations.
32. For Loops: In the previous video, we
discussed how to represent collections of items using
lists, tuples, and sets. Moreover, we
highlighted the benefit of using collections when
storing large amounts of data and studied how PyTn's powerful built in methods can help us manage
those collections. But as we're about to see, managing large collections of items can sometimes
be quite challenging. For example, suppose you're
the owner of a store who wants to discount all
inventory items by 30%. To accomplish this task, we can start by creating an empty list of
discounted prices. Then we may utilize indexing
to access each price, multiply it by 0.7, and append the result to
the discounted price list. But as you can imagine, this will be quite tedious
since there are many prices. Fortunately, there's
a better way. In this video, we will learn how to automate
repetitive tasks like discounting prices using a programming concept
called four loops. By the end of this video, you'll see how loops can
simplify and optimize your code. Let's dive in and
see how it's done. For loops are structures
that allow programmers to execute lines of code for
each item in a collection. The four loop syntax in
PyTon is very intuitive. To appreciate the
simplicity of the syntax, we'll write a simple
for loop that discount the prices
in the prices list. Specifically, we'll
do the following. For each price in
the price list, let's apply a 30% discount and append the result to the
discounted price list. Notice how close the
Python syntax is to the English description
of what we want to do. Let's complete our program with a print statement
and execute the cell to confirm that the loop did indeed apply the
discount to each item. Great. It does look like the discounted price list contains the discounts
we were hoping for. If you have the patience,
feel free to verify. Also note that it took only two lines of code to
achieve the desired output. That's quite neat. Okay, now
that we know the syntax, let's examine the anatomy of the loop a little
bit more carefully. A four loop has two
main components, a header that ends with a
column and an indented body. This structure should look
familiar at this point. Conditional statements, which we covered in
the previous lectures, also follow a similar format. Let's take a closer look at
the header of our four loop. First, the keyword four
instructs Piton that the program is
entering a block of code that might need
to be repeated. The second component of
the header is called an iteration variable
or loop variable. This variable is used throughout the loop iterations to store
the items of the list. We'll say more about that
iteration variable shortly. For now, let's simply note
that instead of price, we could use a different
variable name such as two, two without any impact
on our program's output. But while we are free to choose any name for the
iteration variable, it is better to choose a
representative variable name. In this example, price is
a better name than 22, since it better evokes the nature of the
items in the list. Next, the keyword in is used to introduce the collection
over which to iterate. In this example, we are iterating over a
collection called prices. The length of this
collection determines the number of iterations
the loop will perform. In this specific case, the prices list
contains 30 prices. Therefore, Piton will execute the body of the
four loop 30 times, once for each element
in the prices list. Finally, the body of
a four loop contains the code that PyTon will
execute during each iteration. In this example, the
body of the four loop, discount the price of
an item and append the result to the
discounted price list. Awesome. Now that we have examined closely the
anatomy of our loop, let's study step by step how
PyTon executes that loop. When during the
program's execution, PTN reaches the loop's
header for the first time, it creates the iteration
variable price and assigns it the first
item of the prices list. Then Pyton executes the code
in the body of the loop. In this case, the body of the loop contains a
single line of code, but there could be more. Since the iteration
variable price takes the value 51.79 during
the first iteration, the value 36.25 is appended to the
discounted prices list. Following the execution of the code in the
body of the loop, PyTon returns to the header. At that point, the
iteration variable is reassigned the second
item in the prices list. Then PyTon executes the code in the body of the loop again. Since the iteration
variable takes the value 39.37 during the
second iteration, the value 27.56 is appended
to the discounted price list. Piton then returns
to the header, reassigns the
iteration variable, and executes the code in the
body of the loop once again. This process continues until the iteration variable has been assigned every price
in the prices list. When PyTon runs out of item, the loop execution is complete. PyTon then moves on to executing the remaining
lines in the program. And this is generally how
four loops are executed. One iteration at a time, starting from the
first element of the collection and
ending at the last one. Along the way, the
iteration variable is sequentially reassigned to the next item of the collection. When performing
repetitive tasks, loops have the advantage
of being concise. These two lines of code are indeed doing a lot of
heavy lifting for us. A related advantage of
four loops is scalability. To illustrate this point, let's suppose that
the store manager in our example discovers a few more items to discount and includes their
prices in the list. With a four loop, our code accommodates this change
without any modification. PTN automatically
handles the change for us by performing a few
more loop iterations. Without a loop, we would need to manually track
the items that have been added and write more lines of code to
apply the discount. Great. You now have a basic understanding of
four loops and of why they are sometimes
preferable to applying manually operations to
the items of a list. In the next video,
we will delve into a more complex use
case for four loops.
33. For Loops - Guided Examples: Since the last few
hikes went so well, Jamie decided to plan a more ambitious
two day expedition for the upcoming weekend. Pike likes the idea and
recommends a list of waypoints that culminate at the summit of Pine
Ridge Mountain, where they can camp overnight. Let's represent the
waypoints leading to Pine Ridge Mountain
with a PyTon list. Because this hike will be more complicated than
any previous ones, Jamie would like a list of
tasks they should do at each waypoint to keep their
trek safe and enjoyable. Pike suggests that
at each waypoint, Jamie should drink water, eat a snack, take
inventory of our supplies, and snap pictures to
document their adventure. Always an eager note taker, Pike prepares a list
of those tasks. Let's also represent
this list in Python. Awesome. Now, let's sum up Jamie and Pike's game plan
for their next expedition. From the Trailhead, the two will hike towards
Granite Falls crossing. When they reach the crossing, Jimi will drink water, eat a snack, inventory
supplies, and snap pictures. From there, they will
head to Starlight Meadow. Upon arrival, they will again go through
the list of tasks. Returning to the trail, they'll start hiking towards
Cedar Creek Junction. Once they arrive,
they will once again, complete the list of tasks. They'll then head out
to Evergreen Grove, where you guessed it, Jamie and Pike will
complete the tasks. Finally, after the last
stretch of their hike, the pair will arrive
at Pine Ridge Summit, where they will, one last time, complete the list of tasks. Wow. That was a
lot of repetition. Can we print this to do list
in PTon without having to explicitly type out every
activity at each waypoint? Because that seems
kind of tedious to me. Well, when some
programming tasks need to be performed repeatedly, four loops are there to
help us. Let's see how. First, let's write a four loop that iterates through
the list of waypoints and prints the
arrival message and the departure message
for each waypoint. In between these two
print statements, let's write more print
statements for each of the tasks that should be
performed at a given location. When we execute the cell, we can see that the output
matches the to do list. Now, to make sure that
everything is clear, we'll break down how this
code works step by step. When the program reaches the header of the four
loop for the first time, Biton sets the
waypoint loop variable to Granite falls crossing. Entering the body of the loop, PyTon prints the granite falls
crossing arrival message, followed by each of the tasks, and then the granite falls
crossing exit message. Then in the next loop iteration, PyTon sets the waypoint
loop variable to starlight meadow and repeats the
corresponding print statements in the body of the loop. The loop variable
waypoint is similarly updated at the beginning of each of the remaining
iterations. At the end of the last
iteration of the loop, when the waypoint loop variable is set to Pine Ridge summit, Python returns to
the loop header, notes that there are
no more items to iterate through and
exits the loop. This works fine. Our
code is a lot more compact than if we had written all 30 print
statements manually. But we can actually do better. Notice that in the
body of the Four doop, our code is manually iterating through the indexes
of the tasks list. If there were many more tasks, this would be very tedious. Thankfully, these repetitions
can be eliminated by writing another four loop
within our first four loop. For the record, we call a loop located inside another
four loop, a nested loop. Let's see how we can improve our code with a
nested four loop. To iterate over all the
tasks at a given waypoint, let's create a for loop where for each task in tasks list, we print the name of the task. After executing the cell, we see that the
output again matches what Jamie and Pike plan
to do on their hike. Now, I know, understanding the execution flow of a nested
loop can be challenging. For that reason, let's trade this code for
a few iterations. As before, when Python first reaches the
outer loop header, the waypoint loop variable is assigned the string
granite falls crossing. Then Python moves to the outer loop's body and prints Granite Falls
Crossings arrival message. Next, Python moves to the
header of the nested loop. At that point, the
loop variable task is assigned the first item in
the tasks list, drink water. Moving into the body
of the nested loop, PyTon prints the task. Then PyTon returns to the
header of the nested loop and reassigns the task variable to the second item
of the tasks list. Eat a snack. This
task is then printed. The remaining iterations
of the nested loop are similarly executed before
Pyton exits that loop. Upon exiting the nested loop, Pyton executes the last line of the first iteration
of the outer loop. Then Pyton returns to
the outer loops header, where the variable waypoint is reassigned the value
starlight meadow. And this cycle is repeated for all items in
the waypoints list. To emphasize, the
important takeaway here is that all iterations of the nested loop are
executed before Python moves on to the next
iteration of the outer loop. Awesome. You now have
a handle on loops, and you've seen how they can be nested to solve
complex problems. That being said, four loops are more difficult concept than
the one we've covered before. For that reason, in the
following exercises, we'll give you plenty of
opportunities to practice.
34. For Loops - Exercise Solutions: In this workbook, you
had the opportunity to practice using four loops
in different scenarios. Additionally, you
learned how to use multiple loop variables that enumerate and range functions, loop control mechanisms,
and list comprehensions, which all make four
loops even more useful. Let's break down the solutions. In exercise one, P A, we were given a playlist
and needed to print out the title and duration of
each song using a four loop. Because each element in playlist is a tuple
with three elements, we unpacked our
song loop variable into three individual variables. We then use these variables
inside the print statement. This loop prints out
each song in the list, along with its duration
in minutes and seconds. In Part B, we added a minutes and seconds
counter to our code from part A to calculate the total duration of all
songs in the playlist. Inside the loop, we incremented the total minutes
and total seconds variables to account for
each song's duration. Then after the four loop, we extracted the number
of full minutes from the total seconds variable using the floor division operator and added it to the
total minutes variable. Next, we use the
modulus operator to calculate the remaining
seconds and reassign that value to the
total seconds variable such that this value
won't ever exceed 60. Finally, we printed out
the total duration. Moving to exercise two, we were given a playlist of classic songs and
needed to determine which songs in the
playlist were by the Beatles and create
playlists accordingly. For this, we created
two empty lists, one for the Beatles songs, and one for other songs. Creating these empty lists outside the for
loop ensures that we don't override the lists on each iteration of the loop. In the loop body, we
unpacked the song tuples two items into the title
and artist variables. We then used a
conditional statement to determine whether the
artist is the Beatles. If so, then we appended the song title to the
Beatles Songs List. If not, we appended the song title to the
other songs list. Finally, we printed out
the two lists of songs. In exercise three, we
learned how to use multiple loop variables
to unpack items of a collection directly
in the four loop header. In part A, we were
given a playlist of popular songs and asked to print a report with
the song information. To do this, we used multiple loop variables
to unpack the song name, artist, and album information stored in each
tuple of the list. Finally, we use these variables to print out the
song information. In Part B, we were
given lists of songs, minutes and seconds
and asked to print each song along with its
minutes and seconds duration. Since the three lists are
indexed in the same order, meaning the items at
the same position in each list are related, we used the zip function
to combine the lists. Using multiple loop variables, we immediately
unpacked the song, minutes and seconds data
in the loop header. Finally, we use these variables to print out a useful message. In Part C, we needed to print out the same
lists as Part B, but this time, assigning
a number to each song. To do this, we built
on our code from Part B and added the
counter variable song num. Initially, we set it equal to one so that we may start
numbering the songs from there. We kept song num updated by incrementing it at the end
of each loop iteration. With this modification, we have numbered each of our songs. In Part D, we saw how the
enumerate function can simplify our program from Part C. Instead of creating a
separate counter variable, we passed our zipped lists
into the enumerate function. Then, we created the
iteration variable song num to capture the index returned
by the enumerate function. Because the data we passed into the enumerate function
is a zipped list, the second item returned from the enumerate function will be a tuple containing the song, minutes and seconds data. We directly unpacked
this information in the header using the song, minutes and seconds variables. Note that we obtain the
same output as in part C, but the current version of
our code is more concise. In the last part
of exercise three, we were provided with
a list of tuples, each containing multiple items. Our task was to generate a
report that extracted and displayed only the song title
and its year of release. Since we were given a lot of unnecessary information
about each song, we instead used underscores
in the loop header as placeholders for the values
we did not intend to use. This is good
programming practice, since it makes obvious that this data is not used within
the body of the loop. Moving to exercise four, we were given a top
ten playlist and needed to print the first
five songs in the list. To print just the
first five songs, we use the range function with the argument five
in the loop header. This caused the loop
to iterate five times, sequentially
assigning zero, one, two, three, and four to
the loop variable I. Inside the body of
the loop we used I to index our lists and retrieve
the corresponding song. Note that I is a common
variable name that programmers use to represent
an iteration counter. With this code, we obtained the first five songs
in the top ten list. In Exercise five, we were given a list of
album information. Our task was to print each album and artist along with
the songs in that album. To do this, we needed
to use a nested loop. The Outer Loop
unpacks the album, artist and song information for each item in
the album's list. Using this information,
we printed out the artist and album
inside the outer loop. Then to print out each song
in the songs list that we unpacked in the
outer loop header we needed to create
a nested loop. This inner loop prints
out each song in the songs list before the outer loop moves on
to the next iteration. The output of this
code is the album and artist followed by
each song in that album. Moving to exercise six, P A, we were given a party playlist, where some of the song titles contained the word California. We needed to print only
the songs in the playlist that did not contain the word
California in the title. For this, we created a loop
with the variable song to capture the song name and a placeholder for
the song duration, since we don't need
that information here. Then inside the loop, we tested if the
song name contains the substring California
using the in keyword. This statement we
evaluate to true if the substring California is found anywhere within
the song title. If the song name
contains California, we want to move immediately
on to the next iteration of the loop without executing the remaining lines of
code in the loop body. We use the continue keyword. If the song name does not include California,
it will be printed. As a result, none
of the songs in our output contain
the word California. In Part B, using the
same party playlist, we needed to print each song and the cumulative duration of
the music played so far. However, once we have played music for more than 32 minutes, we need to stop printing songs. To do this, we built
on our solution from part A to include an
additional duration test. At the beginning of
each loop iteration, we checked if total
duration is greater than 32 to determine if it was
time to stop playing music. If it was, we used
the break keyword to immediately break out of the loop and stop
printing songs. If not, then we continued
to our California test. If that test passed, then the song name was printed
and the total duration was incremented to account
for the song being played. The output indicates
that the song Livin' on our Prayer started playing before the 32 minute
mark of the party. Once that song ended, the next song was
not played since total duration was now
greater than 32 minutes. In Exercise seven, P A, we were given a playlist and
used a four loop to create a list of song titles with
more than 15 characters. Inside this loop, we tested if each song met the title
length condition. If it did, we added the song to our long title songs list. Lastly, in Part B, we improved on our code from Part A by using a
list comprehension. Remember, a list comprehension is comprised of several parts. It starts with the expression. Here, we just use the song name, since that is what we would like in the final
Long songs list. Then the list comprehension specifies the item
in the collection. The item creates the
loop variable song that we used in the expression. The collection is the playlist we wish to iterate through. Finally, the list comprehension includes a conditional
statement. This conditional
statement filters out songs with 15 characters
or less in their titles. As a result, we
obtained a list of songs with titles longer
than 15 characters. Great. You've now had extensive practice
using four loops in various scenarios
and explored using new concepts that enhance
their functionality. In the next video, we'll introduce a new data
type, dictionaries. Four loops are especially powerful when working
with dictionaries. So rest assured, you'll have
plenty more opportunities to practice using four loops in the upcoming
dictionaries exercises.
35. Dictionaries: In previous lectures,
we learned about collections such as
lists and tuples. Among other things, we
learned that the items of these collections are indexed
using consecutive integers, zero, one, two, and so on. In many applications,
indexing the items using consecutive integers
is totally appropriate. However, in other instances, we may need more flexible
indexing options. When more flexibility is needed, PyTon provides a different type of collections
called dictionaries. In this video, we introduce the concept
of dictionaries and illustrate why
they are sometimes preferable to other
types of collections. Suppose you want to
collect and store the email addresses of
your three best friends, Bob, Wendy, and Cecilia. To achieve this, we can use
the tools we learned in the previous lectures and create a list of
email addresses. This works in the sense that we have effectively
stored the data. But the way in which the values are indexed is not as
informative as it could be. For example, suppose that at
some point in the future, you consult your list to retrieve Cecilia's
email address. Well, that might be more
difficult than it should. Is Cecilia's email the zero first or second
element in the list? Is it Cecilia who loves
bunnies or is it Bob? Who still uses hotmail
in the 21st century? Truly, we are left with more
questions than answers. Indeed, this collection would be more informative
if the values were indexed by the name of our friends instead of
some arbitrary integers. And this is exactly what PyTon dictionaries
allow us to do. Creating a dictionary
starts with an empty pair of curly brackets. Then within those brackets, we pair a key with a
value by joining the two with a column to add more key value pairs
to the dictionary. Repeat the same steps, separating every
pair with a comma. Once the dictionary
has been created, we can retrieve information from it in a very intuitive way. For example, to access
Cecilia's email, follow the name of the
dictionary with brackets. Then instead of specifying the index of the element
as we did for list, write the key Cecilia in
between the brackets. And Tara, we have successfully retrieved Cecilia's email address
from the dictionary. As a side note, we
can also retrieve elements from a dictionary
by using the G method. This method takes a key as an argument and returns
the corresponding value. As you can see, when
using a dictionary, there is no need to remember some abstract index to access
the information we want. For that reason,
dictionaries often provide a more intuitive way
to organize information. Now that we have covered the fundamentals
of dictionaries, let's make a few observations. First, the keys of a
dictionary must be unique. In the context of our example, this means that we could not add another email address associated
with the key Cecilia. As you can see, when
the same key is included twice in the
dictionary's definition, one of the two key value
pairs is rejected. But this restriction does not extend to the values
of the dictionary. The values of a dictionary
can be duplicated. For example, if we create another dictionary to store the physical addresses
of our friends, giving Cecilia and Wendy the same address
is not a problem. Next, various data types can
be used as keys and values. But as far as keys
are concerned, strings are by far the most
commonly used data type. Accordingly, we'll only be using strings as dictionary
keys in this course. As far as values are concerned, a wide range of data types
is used in practice, such as integers, floats, booleans, lists, and
even dictionaries. You will get to explore some of the possibilities
in the exercises. In the next video,
we will explore additional operations and
methods on dictionaries. Moreover, we will see how dictionaries can be used to store complex data structures, a very useful feature in
practice. I'll see you there.
36. Dictionaries - Guided Examples: After a short but
restful night of sleep, Jamie and Pike are getting ready to make the trek back
down the mountain. As they're about to
leave, Jamie asks Pike if he could document
their journey back home. She would like him
to prompt her with a few questions every 3 miles
and record her answers. Pike enthusiastically
agrees and creates a system to organize Jamie's
responses in his notebook. First, Bike creates
journal entries for the miles at which he needs to ask questions to Jamie. Then under each mileage entry, Bike writes the questions
he must ask Jamie. That's a great way to
organize information. If you look closely,
you'll notice that Pike's organizational
system appears to have a key value structure, albeit with an extra
layer of keys. In this scenario, the mile
markers are obviously keys, but the questions also
appear to be keys. Interesting, how are we going
to represent that in Piton? Here's a hint, just like we
can create a list of lists. It is also possible to create a dictionary of dictionaries. That's how we'll
get the extra layer of keys. Let's see
how it's done. We start with an
empty dictionary and then define
the mileage keys. Next, we assign the values associated with
each mileage key. In Pike's organizational
structure, the value associated with a given mileage
key is a group of question answer pairs that can themselves be represented
with a dictionary. Because we do not know Jamie's
answers at the moment, we will initialize the answer to each question with
an empty string. By copying the question answer dictionary for the
other mileage keys, we recreate Pike's
organizational structure. This method for creating a dictionary of
dictionaries works. But all the copy pasting is somewhat cumbersome,
would you agree? When programming, if you find yourself copying
multiple lines of code, there's likely a
more efficient way to achieve what you want to do. In what follows, we will see
how to build our dictionary of dictionaries iteratively
using four loops. But before we get going, we need to discuss
how to add an item to an existing dictionary as it is an important
building block. For example, let's say we have an empty dictionary
named my dictionary, and we want to add to it the key value pair,
My number three. This can be done by assigning the value three to the
new key, My number. If you'd like to
add more key value pairs to your
dictionary, no problem. We can similarly assign additional key value
pairs to the dictionary. Okay, with that out of the way, let's see how we can cut
down on the copy pasting and build our dictionary
using a loop. We will proceed in three steps. First, we must create the empty Trilog
dictionary and define the list of mile markers and questions we want
to use as keys. Second, we use a first four loop to create the outer
layer of keys. More specifically, we write a four loop that iterates over the mile markers and assign an empty
dictionary to each key. This point, we have created
the outer layer of keys. The third and final step is to create the dictionary's
inner layer of keys. We will do this by creating
a nested four loop to iterate over the items
of the questions list. In the body of our nested loop, we assign an empty string to all the mileage
question keys. Executing the code, we
can see that we have indeed replicated the
original dictionary. The syntax of the line of code
in the body of the nested loop works just like it did in the context of
multidimensional list. More precisely, Tra Log Miles selects the
dictionary associated with the current
mileage number key. For example, during the first iteration
of the outer loop, this refers to the
mile three dictionary. The second bracketed term
referenced the key of the nested dictionary to which we want to assign
the empty string. This implies that during the first iteration
of the nested loop, this key is assigned
an empty string. Note that by using four loops, we have created
our dictionary of dictionaries with
much less effort than typing out each
individual entry manually would have required. Moreover, the four loop
approach is more scalable. We can add another mileage
marker or another question to our dictionary without making any changes to the four loop. Awesome. Jamie and Pike are now ready to
begin their descent. After working their way through some steep and
treacherous trails, our hikers arrive at mile three. Right on cue, Pike asks
Jamie how she is feeling if she has seen any cool wildlife and how the trail
conditions were. Jamie responds that she
is feeling energized, that she saw two elk and moose, and that the trails
were rocky and steep. To update our dictionary
based on Jamie's answers, we first write the name
of our dictionary, followed by the mile three key. This gives us access to the corresponding dictionary
of questions and answers. Then we write the key of our
first question for which we want to update the answer and assign the
corresponding value. We can then similarly update the answers to the
other two questions. Executing the cell, we
see the updated values of all the questions
associated with mile three. Wonderful. After recording
Jamie's answers, the two adventurers continue their trek down Pine
Ridge Mountain. The trail between
mile three and six is much less rocky and winds
through a dense forest. Jamie even spots a large bear
at the bottom of a ravine. As they cross the mile six
milestone of their trek, Pike once again, asks Jamie
the questions on the list. Slightly exhausted, Jamie still finds the energy to
answer Pike's questions. Jamie let him know that she
is feeling tired and hungry, that she saw a bear and that the trails were covered
in roots and overgrown. As you have probably noted, separately typing
out each update to our dictionary is
somewhat cumbersome. When we previously
recorded Jamie's answers, we performed three
separate assignments. That's fine, but in some cases, we may want to be able to update multiple key
value pairs at once. In such situations, the update method can
make our lives easier. This method takes a dictionary
of the key value pairs to update as an argument and modifies the dictionary
accordingly. Executing the cell, we
can see that all of Jamie's mile six
answers have been added to the trail log
in a single statement. Once Jamie's answers
have been recorded, our adventurers resume hiking. On the last leg
of their journey, the trail conditions
improve significantly. As a bonus, Jamie sees two bison in the distance
as they near the trailhead. When the pair reaches the end
of the trail at mile nine, Jamie anticipates
Pike's questions and tells him that she feels
tired but accomplished. She also notes that she saw two bison and that the
trails were well maintained. In our code, we
can once again use the update method to add this new information
to our trail log. But instead of manually
typing out each question key, which provides the
opportunity to make a typo, we can index our questions list. Not only is this
less error prone, but it saves us some typing, executing the cell, we
see that the questions associated with the key mile
nine have been updated. Awesome. You now understand how dictionaries work and how
to interact with them. In the following exercises, you will practice
using dictionaries in various contexts and learn about a few more useful methods.
37. Dictionaries - Exercise Solutions: In this workbook, you got
hands on experience with using dictionaries to organize
and structure information. You also explored how powerful four loops can be when working
with dictionaries. Now let's go over the
solutions together. In exercise one, Part A, we were given information about three art pieces and needed to store that
information in a dictionary. To make it easy to look up
artworks by their name, we set up the dictionary with
the artwork names as keys. For each artwork, we
included the artist and genre information by creating a nested dictionary with
these attributes as values. This way, all relevant
information for each artwork is neatly organized
and easily accessible. In Part B, we were provided with additional art pieces to
add to our dictionary. Instead of manually typing
out all the information, which would be quite tedious, we have leveraged a
four loop along with the provided lists to efficiently and programmatically
build the art gallery. This approach saved time and
reduced the risk of errors. There are at least two ways to create a dictionary
from the given lists. First, we use the
range function, which generates a
sequence of numbers from zero up until the length
of the provided lists. We then use these numbers
to sequentially access the data at the corresponding
indexes in the lists, creating key value pairs for
our art gallery dictionary. Alternatively, we took
advantage of the ZIP function, which neatly combines the
three lists together. By unpacking the data directly
in the four loop header, we were able to create
key value pairs for our four loop dictionary in a more concise and readable way. In part C, we were given two more artworks and needed to add them to our art
gallery dictionary. The best way to do this is
using the update method, since it allows us to
make a single method call to update our dictionary
with both new entries. We passed in the new
entries as key value pairs, and Python added them to
our art gallery dictionary. Alternatively, we
could have used index notation to
create new entries. However, this
approach comes with a bit more overhead
as we need to first initialize the
empty dictionaries before assigning each
value separately. While this is a
perfectly valid method, the syntax is a bit more cumbersome compared
to the update method. In Exercise two, Part A, we were tasked with printing
the names of all of the art pieces in the
art gallery dictionary using just two lines of code. To achieve this, we use the Keys method along
with a four loop. The Keys method gave us access to the names
of the artworks, and we then printed each
name within the loop's body. This approach
efficiently displayed all of the artwork names
with minimal code. In part B, we were asked
to print the artist names associated with each work by iterating through
the dictionary values. The value associated
with each key in the art gallery dictionary
is another dictionary. To access the artist's name, we retrieve the value
associated with the artist key within
this nested dictionary. This allowed us to print the artist's names for
each artwork efficiently. In Part C, we were
tasked with printing the name of the artwork and
its corresponding artist. To do this, we use the
items method to unpack each key value pair from the dictionary into
two loop variables, one for the artwork name
and one for the details. Inside the loop, we printed
the artwork name and access the artist value from the details dictionary to
include it in the output. This approach
allowed us to neatly display each artwork
alongside its artist. Next, in exercise three, we needed to check our art
gallery dictionary to see if it contained the artwork
called American Gothic. To determine if American Gothic is in the Art
Gallery dictionary, we created a simple
conditional statement. The conditional
expression used the in keyword to check whether the work existed
in the dictionary. With this conditional block, we obtained that American
Gothic is in the Art Gallery. In Exercise four, Part A, we were required to remove American Gothic from
the dictionary. We accomplished this by
using the pop method, which removes the specified key and its associated value
from the dictionary. The cell output confirmed that the American Gothic
key value pair was successfully removed. In part B, we needed to remove two works from our dictionary and print their information. We accomplished this by using a four loop to iterate
through our loaned art list. For each work in the
loaned art list, we removed it from the
art gallery dictionary by passing the work name as an
argument to the pop method. Since the POP method returns the value associated
with the removed key, we stored that value in a
variable called removed art. This value is a dictionary that contains the artist
and genre information. In the print statement,
we displayed the name of the work using
the loop variable work, and we printed the
associated artist and genre information stored in
the removed art dictionary. Because the removed art variable contains a nested dictionary, we use the G method
to specifically access and print the
artist and genre values. This approach allowed
us to cleanly remove the works and
display their details. Finally, in Exercise five, we tackled some harder problems. In Part A, we used a list comprehension to
streamline the process of finding and printing all
of the works created by Leonardo DaVinci in our
art gallery dictionary. Let's break down how this
list comprehension works. Recall the structure of a list comprehension.
First is the expression. This determines what each item in the resulting list will be. In our case, the expression is the piece variable representing
the artwork names. Second, we define
the loop variables. These are the variables we use to iterate over
the collection. Here we have piece and details where piece refers
to the artwork name and details refers to the nested dictionary containing the artist and
genre information. Third, is the data we
are iterating over. In this instance, it's the items in the art
gallery dictionary. Finally, we have
the condition which filters the items based
on a specific criteria. We use the details loop
variable to check if the artist's name for
the current piece is Leonardo Da Vinci. If this condition is met, the work is included in
the final results list. If not, it's skipped. When the list comprehension
finishes executing, we're left with a list of all the works created
by Leonardo DaVinci. This concise approach
reduces lines of code and makes it easier to focus on the essential logic of the task. In Part B, we needed to count the number of art
pieces by each artist, and we did this using 24 loops. In the first loop, we iterated
through the values of the art gallery dictionary to find the artist
for each work. We then checked
if the artist was already in the artists
summary dictionary. If they were, we incremented the value associated
with their name by one. But if they weren't, we
added a new entry for that artist in the artist's summary dictionary and
set their count to one. In the second loop, we
use the items method to iterate through the keys and values of the artists
summary dictionary. In the loop header, we
unpacked the output of the items method
into two variables, the artist's name and the number of works
associated with them. We then printed
this information, giving us a clear
summary of how many artworks each artist
had in the collection. Awesome. You've now gained
substantial experience working with dictionaries and sharpened your skills working
with four loops. In the next video, we'll
explore how to make our code more interactive as we dive
into handling user input.
38. User Input: In this course, we have
so far focused on writing programs that do not interact with the user while
the program is running. Essentially, we've been running code and waiting for
the output to show up. However, in practice,
user inputs are often useful for creating dynamic and responsive programs. In this video, we'll study
how to make our program more engaging by
integrating user inputs. I'll start by introducing
the input function, which is the primary way to
request user inputs in PyTon. The role of the
input function is to prompt the user
to enter data, which our program
can then process. For example, let's write a simple program asking the
user to provide their name. This can be done by simply calling the input
function as follows. Fine. But without any context, it might be difficult
for the user to understand what information
the program expects. To help the user, we can pass as an argument
into the input function, a message to be displayed
before the input prompt. Much clearer. Once the user has typed in the data
and pressed Enter, the user's input is
immediately returned to the program and displayed
in the output box. That's cool. But if we ask
a user for their input, it's likely because we want to do something with that
input in our program. To collect the user's input, we assign the return value of the input function
to a variable. From there, you may
use the variable in the rest of the program
like any other variable. Great. Now that we know the fundamental features
of the input function, let's make a few
additional remarks. First, when Python executes the line containing
the input function, the program pauses and
waits for the user's input. Once the user has
submitted their input, the execution of the remaining
lines of code resumes. Second, it is best
practice to write clear and precise
text prompts so that the user knows what information they are expected to input. Third, regardless of the
value the user supplies, the input function always
returns that value as a string. If, for example, we
write another program to ask the user for their
age and they input a number, this number is
returned as a string. This is not really an issue in practice because
numbers represented by Python strings can
always be converted back to the appropriate data
type inside the program. It's just something
to be mindful of. Relatedly, it is
good practice to immediately cast
the user's input to the expected data type. This way, we can safely
assume that the data is of the appropriate type in
the remainder of the program. Finally, to provide a
smooth user experience, it is best practice to
provide some confirmation that the input was
received. Great. As you've seen, user inputs
make programs flexible by allowing the user to guide the program's execution
in real time. However, user inputs sometimes create additional
programming challenges. For example, users may
provide unsuitable inputs. In the next video, we
will study how to handle those unexpected inputs and make our programs more robust.
39. Error Handling: In the previous
video, we saw how to request user inputs during
the execution of a program. In many applications,
user inputs are necessary to determine the
execution flow of a program. However, users can input
anything in an input box, which can lead to unexpected
behavior or errors. To make our programs more
robust and user friendly, we need to handle these
errors gracefully. In this video, we
will see how to use PyTn's error handling mechanism to manage and handle
those errors effectively. Let's start with a simple
example to show what happens when we don't
handle errors properly. Consider this program
that prompts the user to provide two numbers and
returns their cotent. This program works as intended as long as the user
provides valued inputs. However, if the user enters
something unexpected, then the program crashes. We can safely assume that
for the average user, the message on
screen is Gibberish. Receiving an output like that results in a poor
user experience. To improve the
user's experience, we need to handle these errors, also known as
exceptions so the user can understand why their
input was incorrect. To catch and handle
the SPSC errors, PyTon provides the try
and except keywords. We use those
keywords as follows. Under the try statement, we intend the code we are concerned could
cause an exception. If a line of code in the
tr block causes an error, Pyton moves down to the except block without executing the remainder
of the trilock. In the except block, we write code that
either addresses the error or outputs an
instruction for the user. On the other hand, if there is no error in the execution
of the tri block, the except block is skipped. Let's implement a tr except block in our tient
calculator program. We start by writing
the tri keyword above the potentially problematic code and indenting the
lines of concern. Then we write the
except keyword on the same level of indentation
as the tr keyword. Under this keyword, we write the code we want to execute
if an exception occurs. In this case, it
suffices to print a simple statement informing
the user that an error has occurred and providing
instructions about how to fix the error the next time
the user runs the program. Let's test our modified code. When the user provides numbers, the program delivers the
same output as before. But on the other hand, if the user inputs
non numeric data, the program now handles
the error more gracefully. The program's output tells
the user that something went wrong and that they should input numeric data next time
they run the program. However, inputting
a word instead of a number is not the only
mistake the user can make. For example, if we rerun our program and input
zero as the denominator, our program outputs the
same error message. But in this case, the
two inputs are numbers. This error message is confusing. The issue here is that we
attempted to divide 12 by zero. This produced an error which was then handled by our
exception block, which in turn printed the
error message on the screen. Wouldn't it be better if
our program could handle non numeric data and division
by zero errors separately? Well, that's possible to catch and handle different
types of errors separately. We need multiple except blocks. For each except block, we must specify the type of error the block
should handle. To determine the
type of an error, we can replicate the exception
in a different cell. The error is given as the
first line of the output. In this case, the exception
type is value error. So this is what we must write in the except statement that
handles this exception type. Similarly, to
determine the type of exception associated
with division by zero, let's replicate the error. We find that the exception
type is zero division error. Let's add that information to
the second except statement and change the message in the blocks body to
be more informative. Great. In summary, this new version of our
program gently directs the user to input a number if they mistakenly entered
something else. Moreover, the program
instructs users to choose a non zero denominator
if they made that mistake. Finally, if the numerator
and denominator are valid, the program calculates the tent. Now, this modified version
of our program provides a much better user
experience. Great. You now know how to write robust programs that
accept user inputs. In the next video, we will
explore a few more situation where good error handling
can improve user experience.
40. User Input and Error Handling - Guided Examples: Jamie and Pike's two day
hike was a great success. Sure, I took them a
few days to recover. But now that they
are well rested, the two are eager to attack
a more ambitious trail. After reviewing various options, Pike proposes a
five day hike that will take them to a different
campground each night. Given this adventurous length
and anticipated intensity, Jimi needs to ensure
that she carries the right amount of water at
the beginning of each day. That is enough to stay hydrated, but no more than necessary or she will needlessly
carry extra weight. Thankfully, Pike can help. He inquires about
the duration of Jamie's hike to calculate the
required amount of water. Similarly, we can use
Piton to ask a user to enter the length of their hike
using the input function. From experience, Pike
knows that 24 ounces of water per hour is what Jamie
needs on an average hike. Therefore, we can answer Jamie's question by casting
the user input to a float, multiplying the
resulting number by 24, and printing the result. Jamie informs Pike
that she expects to be hiking for about
6 hours a day. Pike takes our input and Oops, it looks like Pike is unable
to process Jamie's answer. Moreover, the error message that Pike returned is
confusing to Jamie. This gibberish doesn't
mean anything to her. All right. Pike Waters
calculation program doesn't handle errors very well. Unfortunately, our PTN program
doesn't fare much better. We receive a similar
error message if we execute the code and
provide the same input. However, we know how to
address this issue in PTN. To handle exceptions of
the value error type, we know that we can indent the potentially
dangerous code under a try statement and then
under an accept statement, write a helpful error message. Re running the cell and
providing the same input as before produces a helpful and
informative error message. Similarly, after a little bit of introspection and
self improvement, Pike was able to implement
better error handling. So he invites Jamie to
give it another try. Not knowing what was wrong
with our first input, Jamie gives Pike the
same input again. But now, in it's
upgrade aversion, Pike's error message is
much more helpful to Jamie. She learns that she must input a numerical number of hours. Provided with a valued input, Pike responds that
Jamie needs to bring 144 ounces of water with her. This is amazing.
Jamie will now be able to delegate water
calculation to Pike. User input and
error handling are useful tools for creating
dynamic programs in PyTon. While we have covered
the basics here, such as using the Tri and except blocks to handle
unexpected inputs, there's a lot more to cover. The upcoming exercises will give you hands on practice
with these concepts. For those interested
in learning more, there's additional resources
available in the appendix.
41. User Input and Error Handling - Exercise Solutions: In this workbook, you've
practiced asking users for input and managing any
errors that might come up. Let's break down the solutions. In Exercise one, Part A, we needed to translate
English words into Zonian using the language
translator dictionary. To achieve this, we first ask the user to input the word
they want to translate. Next, inside the Tri Block, we attempt to find the word in the language
translator dictionary and print the translation. If the word lookup fails, we handle the error
in the except block. This ensures that the program handles missing
translations smoothly. The final program prompts
the user to enter an English word and then
provides the Zonian translation. In Part B, we focused on the else clause and used it to improve our
code from Part A. Since the word lookup
might cause an error, we keep that code
inside the trilock. Because we only want the
print statement to execute, if the word lookup succeeds, we move it to the else block. Remember, the else Block
ensures that the code within it only runs if the
entire triblock succeeds. In Exercise two, part A, we needed to create
an English to Zalonian unit converter program. To do this, we ask the user to enter the earthly unit
they wish to convert. Within a triblock we attempt to retrieve the
conversion factor from the measurement translator
dictionary using the provided unit and the string conversion
factor as keys. If the lookup fails, we catch the resulting key error
in the except block. Next, since the program should only ask for the
quantity to convert, if the user provides
a valid unit, we embed a second
error handling block inside the first else block. The nested except block handles
the value error that will occur if the user's input can't be converted into a float. Finally, the LSE block calculates the conversion
and prints the result. Writing the quantity input logic here ensures that
the conversions are only attempted
when both the unit and quantity inputs are valid. The final program prompts the user for an earthly unit and quantity then outputs the corresponding
Zalonian conversion. In Part B, we improved
our code from part A by standardizing
the user inputs. We use the lower
and strip methods to clean up the inputs, ensuring that any
extra spaces or variations in capitalization
won't cause issues. This makes our code
more robust against improper user inputs and provides a smoother
user experience. In exercise three, P A, we needed to convert
kilometer distances to their Zalonian equivalent. To achieve this, we
first ask the user to input the number of
distances they wish to convert. We standardize this
input and handle the value error that may occur
during the integer cast. Next, we embed the remaining
code inside an else block to ensure it only runs if the user provides a valid input. Inside the else block,
we create a four loop to iterate through the number of distances the user specified. We pass the user's
previous input into the range
function to generate a sequence of numbers from zero up to but not including
the number of distances. Additionally, we use
a place holder for the loop variable since it's
not used in the loop body. Within the loop we include
an error handling block that asks the user to input a distance and attempts
to cast it to a float. If the conversion fails, the resulting value error is
caught in the except block. If it succeeds,
the valid quantity is converted and printed. The final program asks the user to input the
number of distances they want to convert
and then asks them for a distance to convert
that number of times. In Part B, we enhanced
our English to Zalonian translator to
accept multiword phrases. To do this, we first
ask the user to input an English phrase and
then standardize the input. Next, we use the
split method to break the phrase into a list
of individual words. Then we iterate through this list of words
with a for loop. Inside the loop, we
attempt to translate each word and append the translation to
a translation list. We also include an
except block to handle the key error that occurs if a word is not found
in the dictionary. If a word can't be translated, the program breaks out
of the loop early, and as a result, the
translation list will not be as long
as the words list. This is why we have
to check to see if both lists have
the same length. If they do, that means that the entire phrase
was translated. And if they don't, that means that at least one word
couldn't be translated. This approach ensures
complete translations while handling untranslatable
words effectively. The final program
prompts the user for an English phrase
and then outputs the entire phrase
translated into Zalonian. In Exercise four, we saw a
few more advanced concepts. In Part A, we created a
Zilonian to English translator. Translating from Zonian
to English using the language
translator dictionary is a bit more complex
than the reverse. This is because
Zilonian words are stored as the values
in the dictionary, so we can't directly
look them up like we can with the English
words, which are keys. Instead, we used a four loop combined with the
items method to iterate over all
the key value pairs in the language
translator dictionary. During each iteration,
the program checks if the current dictionary value matches the Zonian word
we want to translate. If a match was found
in the dictionary, we print the English word, which is the dictionary key that corresponds to
the Zonian word, which is the dictionary value. We also set the word found variable to true and
break out of the loop. If a loop finishes without finding a matching Zonian word, the word found variable
remains false. We check the value
of the word found variable to determine if the
translation was successful. If it's not, we raise
a custom value error, catch it in the except block, and provide a helpful
error message. The final program takes the Zonian word as input and
translates it to English. In Part B, we improved our Zonian to English
translator to accept phrases. This problem combines
concepts from exercise three, Part B, and Part A
of this exercise. Like in Exercise three, Part B, we split the input phrase
into individual words using the split method and iterate through each word with a loop. Within this loop, we
write another loop to search the values of the
language translator dictionary, similar to Part A
of this exercise. After the inner loop
finishes searching for the Zonian word
in the dictionary, the program checks if
the word was found. If the word wasn't found, we raise a value error with a
custom informative message. To handle the error, we
use the as E notation to capture the custom error message and print it within
the except block. Finally, if all of the words were
successfully translated, we print the complete
translation. Now, the program
allows us to input Slonian phrases and get back
their English translation. In Part C, we needed to convert multiple
measurements at once. To do this, we first
ask the user to input the measurements as
a comma separated list. We then split this input into a list of individual
measurements. Using a four loop, we iterate through each
measurement in the list. Inside the loop, we
attempt to split each measurement into
its quantity and unit. Next, we try to cast
the quantity to a float and look up the
corresponding unit in the measurement
translator dictionary. If the unit isn't found, we use the rays keyword within the tri block to
create a custom error. Finally, we convert
the quantity from earthly units to Zonian
units and print the results. The final program takes a
series of comma separated earthly measurements
and converts each one to its
Zlonian equivalent. Awesome. Now you have a
solid understanding of how to take user input and
handle the resulting errors. In the upcoming videos, you will learn how to
leverage while loops to further improve the user
interactions in your program.
42. While Loops: In previous videos, we saw how powerful four loops can be to automate repetitive tasks. However, as helpful as they are, four loops have limitations. An important limitation of four loops is that the
number of times the loop should be run must be known at the time the program
enters the loop. Unfortunately, in
many situations, it is not possible
to know how many times a loop should be run
before we run the code. For those situations, four loops are the
wrong tool for the job. Thankfully, another type of loops called Wil loops
can be used instead. In this video, we
introduce this notion of wild loops and discuss when they should be used instead
of four loops. To illustrate the
limitation of four loops, let's recall the example of the store owner who is
discounting inventory items. In this example, the
store owner wants to discount the prices in
a predetermined list. The length of the price list is known before
the loop executes, and it determines the number of iterations the
loop will perform. For that reason, using a four loop is appropriate
in this context. But now let's modify
this example slightly. Suppose the store
owner doesn't know the list of items that must be discounted when they
run the program. Instead, they would
like to manually enter the price of the
items they want to discount as they
process the inventory. Moreover, let's assume
the store owner doesn't know how many items
they will have to discount. All right. Let's
see how to modify our code to satisfy the
store owner's requirements. Since the store owner no longer provides us with a
predetermined list of prices, we should remove it
from the program. This immediately creates an
issue with the for loop. The iteration list
no longer exists, so we can no longer use the iteration variable.
But that's okay. We can still instruct PyTon
to repeat a piece of code by replacing our for loop
with a while loop. A while loop executes the
piece of code in its body repeatedly as long as a control condition specified
in the loop header is true. Finally, let's make the
necessary modifications to the loop's body. Remember, the store owner wants to be able to input the
prices to discount. So let's write an
input statement. Great, to familiarize ourselves with the execution
of a wild loop. Let's run our program and
trace a couple of iterations. Because we assign true to
the should iterate variable, the program enters the body of the Wil loop and we are
prompted to enter a price. When we enter the price, the program applies the discount and prints the sale price. Having reached the last
line of the Wil oops body, the program returns
to the header and tests whether the control
condition is true. Since the value of the shoot iterate variable is still true, the control condition
is also true, and the program proceeds with a second iteration of the loop. This explains why we have
been prompted to enter a second price immediately after submitting the first
one. This is great. No need to rerun the code to
discount additional prices. That's the power of Y loops. But the keen eyed among you may have noticed that there is a slight problem
with our program. If you haven't noticed it yet, think about the execution
of our loop for a second. When exactly will our
program exit the loop? Well, since we are not modifying the should iterate variable
in the loop's body, the control condition in the loop header will
always be true. This in turn implies that the program will
never exit the loop. Oh, no, we have created
an infinite loop. The user will be
prompted to enter prices until the end of time.
What are we going to do? Well, there is no need to panic. We simply need to design a mechanism to
assign the variable should iterate to falls when
we want to exit the program. A common way to achieve
this is to instruct users to enter a specific input when they wish to
exit the program. To implement this,
we first test if the user input equals
this special value. If it is, we reassign
the value of the should iterate
variable to false. If it is not, we
calculate the discount, output the price, and move on to the next iteration as before. Awesome. Et's rerun our code to verify if it
works as intended. During the first iteration
of the wire loop, our program asks for a price. We input 24.58, and the program outputs the
discounted price 17.21. If this is the only price
we want to discount, we enter the exit
value minus one, and the program
terminates gracefully. Amazing. However,
the way our program handles unexpected user
input is less graceful. For example, if a
user mistakenly inputs a string, the
program crashes. Oh, not a great user experience. But we have seen this error before and we know
how to handle it. So let's improve
the user experience by indenting the
dangerous code under a tri block and handling the value error in
an except block. Nice. While the previous
version of our program was allergic to cats and showed no mercy upon
encountering that word, the new version of our code
is much more forgiving. When the user makes a mistake, the program is able to
recuperate and redirects the user to enter a valued
input in a new input box. Much better. To
conclude this video, let's take a step back
and cement in our head the difference between
four loops and wild loops. As you have seen in this video, an important limitation of four loops is that we must know how many iteration the loop will perform before its
execution starts. This condition is satisfied in many if not most applications. However, there are
situations where we cannot know how many iterations of the loop a program will need. This is often the case
when working with user inputs and in some
other contexts as well. In these cases, the
indefinite nature of Wil loop iterations makes this type of loop
the best choice. Wile loops are powerful
tools that Python provides to write
efficient and simple code. In the next video, we'll explore a different scenario where
Wil loops can be helpful.
43. While Loops - Guided Examples: Jimmie and Pike are almost ready to head out on
their five day adventure. To ensure she does not run
out of water during the hike, Jamie intends to carefully track how much
water she has left. Each time Jamie's thirsty, she'll tell Pike how much
water she wants to drink, and Pike will calculate
the amount remaining. Following Pike's
previous recommendation, she will begin the first
day of the hike with 144 ounces of water. Let's write a PyTon program that can accomplish Pike's task. We'll start by creating a variable to store the
remaining ounces of water and initialize it to 144 since this is the volume of water JM starts
our journey with. From there, our program must query the user for
the amount of water they want to drink and adjust the ounces of
water accordingly. Because it is
difficult to predict the exact number of times
the user will drink water, requesting the
user's input within a while loop is the
right thing to do. For now, we leave the control condition
of the loop blank, but we'll return
to it when we have figured out the
body of the loop. Once the user has entered how much water they
want to drink, we find ourselves in
one of two situations. One possibility is that there is enough water remaining to
drink the desired amount. In that case, we subtract
the input at quantity, reassign ounces remaining, and print the result
of our calculation. If that's not the case, the user can at most drink the
amount of water remaining. Accordingly, we let the user know how much water they
can actually drink, inform them that they
are now out of water, and reassign zero to
ounces remaining. Awesome. Now that we have
built the body of the loop, let's move back to
the loop's header to write the control condition. I will argue that the
program should only ask the user how much they want to drink when there is
still water left. Otherwise, it's just rude. Accordingly, as a
controlled condition, we test if a strictly positive
amount of water remains. As long as this
condition is true, it is sensible to
query the user. But when this
condition is false, it is time to exit the loop. Now, of course, it
is possible that the user completes their hike before running out of water. To enable the user to exit
the program gracefully, we can invite them to input
the value minus one to quit. When the user is allowed
to enter an exit value, the first thing our
code should check is whether the user input
is the exit value. If it is, we output
the number of ounces remaining and use the brake
keyword to exit the loop. If not, we execute the remainder of the
program as before. Note that a break statement is a convenient way to handle the user's request
to quit the program. But as we saw in the last video, it is not the only way. Awesome. Jamie and Pike are
now ready to hit the trails. About an hour into their hike, Jamie is feeling thirsty. The two pas as Jamie
drinks 19 ounces of water. If we execute our code
and enter 19 ounces, we obtain that there are
still 125 ounces remaining. Jamie and Pike
then hit the trail again and continue their trek. Along the way, Jamie drinks 25 ounces at the
fork in the trail, 32 ounces at the top
of a steep climb and 18 ounces while
contemplating a waterfall. A few hours into the hike, the two stop for lunch, during which Jamie consumes another 27 ounces of
the scarce liquid. An hour or so after lunch, the pair stops near
a river to rest. Jamie tells Spike
that she intends to drink 25 ounces of water. Unfortunately, that's a tad
more than what's available. As a result, Pike let her
know how much she can actually drink and stops
querying her for more input. Thankfully, Jamie and Pike are only a few minutes
from the cam site. They'll be able to refill when they reach their destination. As you have seen, Wi
loops can greatly improve user experience for
programs using user inputs. In the following exercises, you'll get the chance to
practice using Wi loops to create programs with a
pleasant user experience.
44. While Loops - Exercise Solutions: In this workbook,
you practiced using Wile loops in more
complex situations. Now, let's go over the
solutions together. In exercise one, we created
a program that asks for user inputs to track the number of apples
in the inventory. First, the program asks the user to enter the number of apples
they brought to the market. The input is then
immediately casted to an integer for use in
future calculations. The program then enters a Wile loop that runs as long as there are
apples remaining. Inside the loop, the
user is asked to input the number of apples
sold in a transaction. Here again, this input is
converted to an integer, ensuring that it can be used
for future calculations. The apples sold and Apples
remaining variables are then updated to reflect the number of apples left in the inventory. We then print the content
of those variables. Once there are no
apples remaining, the Wile loop exits. The final program
prompts the user to enter the number of
apples they brought to the market and then
allows them to input the number sold until
they sell out of apples. In exercise two, we wrote a program to track
the quantity of wheat and barley acquired until the user has 20 units of each. To track the quantities purchased, we create
countervariables. We then use a Wile loop with the condition wheat less than
20 or barley less than 20, ensuring the loop will
continue as long as either the wheat or the barley
variables are below 20. Inside the loop, we
prompt the user to input the amount of wheat and barley they have acquired
in a transaction. As an exercise one, we
convert these inputs to integers so we can use
them in future calculations. The wheat and barley
counters are then updated to reflect the new totals and
we print the current counts. The loop ends when
both the wheat and barley variables
reach 20 or more. The final program
asks for user inputs to track the amount of
wheat and barley acquired. In exercise three, part A, we wrote a program to manage the recruitment process
for new guild members. Our goal was to
recruit three members, but we didn't know
how many candidates we would need to evaluate
to reach that goal. We solve this problem
using nested loops. After initializing the number of positions remaining to three, our program enters
a while loop that runs as long as there
are positions remaining. Inside this loop, we first set the trial passed counter
for the current candidate. Next, we create a
nested four loop to request the trial
results from the user. We use the range function in the loop header to iterate
through these two trials. Within the fore loop, we ask the user to input the
result of the trial. If the candidate passes, we increment the
trial's passed counter. After both trials are completed, we test if the trial's passed
counter is equal to two. If it is, we have found a suitable candidate
and the number of positions remaining
is decremented. Otherwise, we indicate failure
by printing a message. The final program
allows the user to input whether a
trial was passed, tracks the number of
member spots remaining and exits once three members
have been recruited. In Part B, we modified
our code from Part A to accommodate the
new recruitment rules. Our program now includes
a new variable, trials attempted to track the running count of a
candidate's attempts. The variable must be reset
for each new candidate, so we place it inside the outer loop but
outside the inner loop. Next, we use a Wile loop to
test whether the candidate still has trials to pass and
trial attempts remaining. This loop runs as long as
the number of successes is less than two and the number of trial attempts is less
than or equal to five. Note that this while
loop may iterate as little as two times or
as many as five times, depending on the
candidate's success. Within the loop,
we still ask for the trial result and increment the trials
passed accordingly. However, now, we also increment
the trials attempted. After the inner loop, we
follow the same logic as in part A to determine if the candidate can
become a guild member. The final program will exit once two members are recruited. In exercise four, we
explored infinite loops. In Part A, we used
the Wil true syntax to continuously prompt the user to input the number
of jokes they sold. Inside this Wile loop, we increment the jokes
sold variable based off the user input and
print the running count. Since there is no
exit condition, we have effectively
created an infinite loop. In Part B, we fix that
infinite loop problem by adding an exit condition
and using the break keyword. Now, if the user
enters negative one, the loop breaks and
immediately stops running. If a user enters anything
other than negative one, we still increment the jokes variable as we did in Part A. The final program will continue
asking for the number of jokes sold until the user
inputs negative one. In Exercise five, Part A, we use a while loop to remove items from
an inventory list. The loop condition inventory is a shorthand way to test
whether the list is empty. It's equivalent to
using the longer n inventory greater than zero
as a control condition. We then test whether the
item is in the inventory. If it is, we use the remove
method to remove it. If it's not, we notify the user. The final program will
continue asking the user to enter an item until there are no items left
in the inventory. Finally, in Part B, we created two equivalent programs to track the intraday profit of a
user's merchant business. In the first program, we
use a control condition to test if the current profit is less than the target profit. This condition ensures
that the loop stops running once the user has saved
enough money for the day. Inside the loop, we
ask the user for the transaction
details and then add the transactions profit
to the current profit. After updating the
current profit, we test whether it is
below the target profit. If it is, we inform the user of their
cumulative profit so far and output how much more is needed
to reach the target. If the profit meets or
exceeds the target, we notify the user that they
have reached their goal. In the second program, we
use the wild true syntax, combined with the break keyword to achieve the same outcome. Both programs will continue
asking the user to input transaction information until the target
profit is reached. Great. You've now seen
how Wile loops can be used in combination
with the concepts we've learned so
far in this course. In the next videos, we will once again upgrade our
programming toolbox by diving into one of the most powerful
programming concepts, user defined functions.
45. User-defined Functions: In previous lectures, we've
used several of PyTn's built in functions such as
print, len and input. These functions helped us perform common tasks
without writing the code ourselves and kept our programs organized
and readable. Unfortunately, PTN
was not built with all the functions that
every situation requires. For example, if you're
an architect who often needs to calculate the
area of geometrical shapes, you're out of luck. There isn't in Bton a
built in function that can calculate a triangles area
or a rectangles area. Fortunately, PTN
enables programmer to define their own function, which are called user
defined functions. User defined functions are prepackaged pieces of
code that can perform a given task such as calculating
the area of a rectangle. In this video, you will
learn how to define your own functions
and explore how these functions can add
value to a program. An architect has designed the floor plan of a new
building called the zigzag. He now needs to
calculate the area of the building's three zones
to order the flooring. Unfortunately, the
architect flunked his geometry class and
never learned how to calculate a rectangles area
given its length and width. Let's help him do
his job by creating a Pyton function that
does this calculation. In Pyton, the definition of a new function starts
with the keyword death. This keyword is followed by the name we want to
give to our function. When naming functions, choose descriptive names that
reflect the function's role, just as you would for variables. Moreover, function names must follow the same naming
rules as variables. In our example, the
name rectangle area is descriptive of what we
want our function to do and adheres to the
four naming rules. So we'll go with that. Next, we follow the
function's name with a pair of parentheses, between which we specify
variable names for the inputs or function
requires to perform its task. Since the length and width of a rectangle are required
to calculate its area, we write variable names
for these two inputs, separating them with a comma. We conclude the header of the function definition
with a column. Next, in the indented
body of the function, we write the operations
necessary to calculate the rectangles
area using the inputs. Here, we multiply the length by the width and assign the
result to the area variable. While we've now calculated
our functions desired output, we're not quite finished yet. Indeed, to make the
calculated area available to the program
that calls or function, we need to use a
special instruction called a return statement. This statement consists of the return keyword followed by the data we want to output. Without a return statement, the result of our
calculation will be lost when the function
finishes executing. We'll soon say more about that. Awesome. Now that we've defined the rectangle
area function, we can use it like any built in function throughout the
rest of our program. To call our function, we
write its name followed by parentheses containing the
rectangle's length and width. At this stage, it
is important to distinguish between
the variable names in the header of the
function definition and the values used in
the function call. As you already know, the values passed into a
function are called arguments. In this example, the
arguments are 100 and 140. The variable names in the header length and width are called the
functions parameters. Parameters are placeholder
variables that receive the argument values
when the function is called. To summarize. While both arguments and parameters refer to
function inputs, arguments are the actual
values used in function calls. Was parameters are
the variable names used in function definition. Okay, now that we've
clarified the terminology, let's run the program to see our rectangle area
function in action, calculating the
area of Zone one. We obtain 14,000 square feet. This probably doesn't come as a surprise for the math
wizards among you, but for our mathematically
challenged architect, this function is a lifesaver. He can now easily
calculate the areas of any building zone without understanding the
underlying mathematics. To the architect, the
rectangle area function acts as a black box. Inputs are provided,
outputs are received, and the internal calculations
remain invisible. As we have seen with
built in functions, this concept known as abstraction is a key
advantage of using functions. By creating user
defined functions, we can package a
set of operations into a single
reusable code unit. These custom functions can encapsulate operations
of any complexity, improving code readability,
and eliminating the need to rewrite
common operations. Once created and tested, user defined
functions can be used as black boxes with users focusing on inputs and outputs rather than
the internal workings. However, to design and implement these
functions effectively, programmers must understand PTon's function
execution process. This includes comprehending
how PyTon manages parameters and variables not only during a
function's execution, but also after it completes. To illustrate this concept, let's trace the code that calculates the area of zone one. The initial lines of code define the rectangle area function. Once executed, PyTon
recognizes rectangle area as a valued function callable anywhere in
the subsequent code. The program then calls
this function with the arguments 100 and 140. When this call occurs, PyTon first creates
two variables, length and width, and
assign them the values 100 and 140 respectively. Then PTN executes
the function body, multiplying length by width and assigning the result to
a new variable area. Finally, PyTon executes
the return statement, passing the calculated area
back to the program and discarding all variables created within the function,
including the parameters. That's an important point. As a result, any attempt
to access the length with an area variables outside the function will
generate a name error. That's because PyTon
considers these variables non existent once the program
has exited the function. In contrast, if we include a print statement within the rectangle area
function itself, PyTon successfully accesses and displays the value of
the area variable. This behavior highlights
an important concept in programming known
as variable scope. In an upcoming lecture, we'll explore the intricacies
of variable scope. But before we go there, let's focus on gaining some
more hands on experience with how to define functions
and how to use them. In the following video, we'll create a few more
functions to gain an intuition for how and when to use them
effectively in our programs.
46. User-defined Functions - Guided Examples: Jimmy and Pike
have now completed the first day of
their five day hike. As they settle down
by a campfire, they reflect on the
day's adventure. Jamie confides in Pike that the day's trek was more
challenging than anticipated. They spend considerably
more time on the trail and consume more of
their food supplies than Pike had
initially predicted. To make sure she
has enough energy and supplies to finish, Jimmy would like to
get better estimates for the remainder
of their journey. Eager to assist, Pike
prepares to refine his forecasting calculations
based on Jamie's input. As we accompany him
in the process, we'll see how functions can streamline code organization
and readability. To generate more
precise estimates, Pike will incorporate data
on the hikes distance, temperature, and tearing
difficulty in his calculations. Let's begin by estimating
the expected hike duration. Under typical conditions, Jamie maintains a steady pace
of 3 miles per hour, which serves as our baseline for calculating hike duration. However, challenging terrain or high temperatures can significantly slow
Jamie's progress. To account for these variables, we need to calculate adjustment factors and modify
our baseline estimate. Let's now calculate the total calorie
expenditure of a hike. As a baseline, Jamie burns approximately 160 calories per hour in typical
hiking conditions. However, challenging
terrain ramps up Jamie's energy output, so we need to adjust
this baseline rate. To calculate the total
calorie expenditure, we first modify the hourly
calorie burning rate based on terrain difficulty, then multiply this adjusted rate by the estimated hike duration. Finally, let's
present our estimates in a clear user friendly format. Awesome. When we run our code, it generates precise
estimates for tomorrow's hike duration and the corresponding energy
expenditure Jamie can expect. And this is the desired output. This is good. However,
the current structure of our code leaves room
for improvement in terms of clarity
and organization. We noted earlier, our block of code performs three
distinct tasks. It calculates the hike duration, calculates Jamie's
energy expenditure, and prints the results. To enhance the
readability of our code, we'll refactor it
by encapsulating the three main tasks
into separate functions. This modular approach will clarify the code's
purpose and flow. Let's start by creating
a function called calc hours to estimate the
time required for the hike. The calc hours function
accepts three parameters. Distance the length of
the hike in miles, temp, the ambient temperature in Fahrenit and terrain difficulty, the rating of the terrance
difficulty on a scale 1-3. In the functions body, we copy the relevant lines of code to calculate
the hike duration. The final line of the
functions body originally assigned the return value to
the variable adjusted hours. However, this assignment
is unnecessary. We can instead directly instruct PyTon to return the
calculated result. By eliminating the intermediate
variable assignment, we've made our code more
concise and efficient. With this function defined, we can simplify the
first code block with a single call to the
calc hours function. Note that when calling
the calc hours function, we passed variables
containing the values ten, 75 and two as arguments rather than passing
the values themselves. When variables are
used as arguments, Biton passes the values
the variable contain to the function and assign those values to the corresponding
function parameters. Here, it's important to understand that the
variable names used in the function call
don't need to match the parameter names in
the function definition. For instance, if we rename the parameter temp to temperature in the
function definition, the calc hours function
still works as intended when called with the variable temp
as an argument. In that case, when the calc
hours function is called, the value associated with the
variable temp is passed to the function and assigned to
the parameter temperature. Great. We'll now follow a similar approach
for the calculation of the calories burned. We first define the
cal calories function, which takes the
duration of the hike in hours and the difficulty
of the terrain as inputs. Then we copy the calorie
calculation code block into the function's body and write the corresponding
return statement. Finally, we replace
the second block of code with a call to the
calc calories function. Note that the call to the
calc calories function takes the output of the calc
hours function as input. Therefore, we must call the calc hours function before calling the calc
calories function. To complete the
revision of our code, we create a third function
called print results, which displays the output. This function takes the
calculated hours and calories as inputs and prints
those quantities in a user friendly format. Note that since the sole purpose of this function is
to print the output, we do not need the function
to return any value. Thus, we omit the
return statement. Lastly, we replace
the output code with the print results
function call. Great. Now that we have
refactored our code, let's run it to confirm
that we still obtain the same outputs.
And indeed we do. But with these changes, we have significantly improved
the structure of our code. By breaking our programs logic into separate focused functions, we've achieved several benefits. Concision. The main
programs body, excluding the
function definitions is considerably
shorter. Readability. Each function has a clear, singular responsibility that can be examined independently. Comprehension, the
program's overall workflow is now more easily understood. Indeed, our new code
structure clearly delineates the three primary
tasks being performed, calculate hiking time,
determine energy expenditure, and print the results. In contrast, distinguishing
these tasks in the original version of the code required more efforts
and careful reading. Pike implements the
requested modifications to it forecasting functionality. To Jamie's satisfaction,
it'll be able to provide more accurate duration and calorie estimates
moving forward. In the last two videos, we explored situations where user defined function improved the quality and
structure of our code. In the exercises that follow, you will practice
two critical skills. First, identifying
situations where user defined functions
are helpful, and second, determining
the scope and the responsibilities of the
functions that you define.
47. User-defined Functions - Exercise Solutions: This workbook, you created several user defined functions to answer various
financial questions. Then you use those functions to help solve financial
problems for clients. Let's discuss the solutions. In Exercise one, we were
asked to write a function that calculates the monthly loan payment given
the parameters, loan amount, annual
interest rate, and number of years
to repay the loan. To do this, we use the three equations given to calculate the
monthly interest rate, number of payments, and finally, the monthly payment amount. Note that the monthly
interest rate and number of payments are used in the
monthly payment equation, so they need to be calculated before we can determine
the monthly payment. When we use the function to calculate the loan payment on a $10,000 loan at 5% annual
interest rate over 30 years, we get a monthly loan
payment of $536.82. In exercise two, we wrote
a function that estimates a client's savings at retirement given the initial
savings amount, annual contribution,
annual rate of return, and number of years
until retirement. Inside this function, we
first create a new variable, total savings and set it
equal to the initial savings. Next, we create a four loop that iterates over the years
until retirement, incrementing the total
savings variable by adding the yearly contribution and growing the investment
at the annual rate. In the loop header,
we create a range of numbers from zero up until
the year's parameter. This range ensures
that the loop iterates exactly once per year
until the client retires. Additionally, we
use a placeholder as the iteration variable, since we will not use this value within the
body of the loop. Inside the loop body, we first increment total savings by the annual
contribution amount. Then we grow the total savings by the rate of return
over one year. Growing the retirement savings
in this way means that we properly account
for the compound growth of an
investment over time. After the loop is
finished running, we return the final
total savings amount, which contains the value of the investor's savings at
the time of retirement. Finally, we use the function to calculate the
retirement savings of a client with a $10,000 initial investment who wishes
to retire in 30 years. With an annual contribution of $5,000 and an expected
rate of return of 5%, their retirement savings
will amount to $392,023.37. Since we used keyword arguments, we could pass the values
into the function in a different order than what
the function specified. As a result, the function
call is more readable, since we know what each value represents within the function. In exercise three, we
wrote a function to project the growth
of an investment given the investment amount, the number of years the investment will
be allowed to grow, and the expected
annual growth rate. In the header of the function, we made this annual growth rate optional by using a
default parameter. Then we calculated
the future value of the initial investment
using the given equation. Finally, we return that value. When we call a function without
an annual rate of return, it uses the default 7% rate. However, when we
do specify a rate, the function uses that rate
instead of the default 7%. In exercise four, we needed to write a
function that performs a budget analysis given monthly income and a list
of monthly expenses. First, the function calculates the total monthly expenses by summing the elements
of the expenses list. Then it subtracts
the total expenses from the monthly income to determine whether the client has a surplus to save or
is running a deficit. The function returns two values, the savings or deficit amount
and the total expenses. In this case, returning
two values is appropriate because the
values are closely related, and this function focuses
on a single task. However, if you find
yourself returning multiple values calculated in a function that performs
multiple tasks, it's better to
split that function into smaller single
purpose functions. When we use this function to analyze a client's budget with $4,000 in monthly income
and this set of expenses, it returns both a
surplus amount of $1,550 and $2,450 in
monthly expenses. In Exercise five, we wrote
a function that analyzes an unspecified number of expense categories using
arbitrary keyword arguments. Arbitrary keyword arguments
allow the function caller to pass in as many
keyword arguments into a function as they wish. Those keyword arguments are collected into a dictionary
called expenses. This means that we can use
dictionary methods like values and items to perform operations on the
expenses dictionary. Inside the function, we
first sum all of the values in the expenses dictionary to calculate the total expenses. Then we iterate over
each key value pair, printing out the category name, amount, and the categories
percentage of total expenses. Finally, we return the
total expenses amount for use outside the function. When we call this
function to analyze a client's list of rent,
groceries, utilities, and entertainment
expenses, we obtain this expense breakdown and
total expenses of $950. Finally, in Exercise six, we use the functions we
created to help some clients. In part A, we helped John
perform a budget analysis. We passed his monthly
income and list of monthly expenses into our
analyzed budget function, which returned the
surplus or deficit amount and the total monthly expenses. John has a monthly
surplus of $3,750, as well as $6,000 of
monthly income to cover his $2,250 of monthly expenses. Then in Part B, we re analyzed John's monthly budget after factoring in his potential
mortgage payments. To do this, we first called our calculate loan
payment function and passed in John's loan
details as arguments. This function returns the monthly loan
payment, and we output. Then we factored this
mortgage payment into John's monthly expenses by appending it to the
monthly expenses list. Next, we called our analyzed
budget function with John's monthly income and
updated monthly expenses. This function returns
the amount of savings or deficit and John's
total monthly expenses. John has a monthly mortgage
payment of $432.25. And based on his
income and expenses, he has $2,317.75 of
monthly surplus. In Part C, we needed to help Maria calculate
her retirement savings. To do this, we called our calculate retirement
savings function, passing in her details
as keyword arguments. Here, using keyword
arguments allows us to pass in the arguments
in any order we wish. Based on Maria's
retirement details, we obtain that she will have $376,083.52 in savings
at the time she retires. In part D, we helped
Lisa track her expenses. We called our Analyze expenses
function passing in each of Lisa's expense categories as arbitrary keyword arguments. We explicitly assigned a
name to each argument, since these names will become the keys of the expenses
dictionary within the function. This function then prints the
expense category breakdown. Lastly, in part E, we helped
Alex project the growth of his inheritance and analyzed his expenses and monthly budget. First, we called our project
investment growth function to calculate that Alex's
$10,000 inheritance will be worth $27,590.32 in 15 years at an annual
growth rate of 7%. Second, we analyzed Alex's
expenses by passing in each of his expense categories into our analyzed expenses function as arbitrary keyword arguments, just like we did
in part D. Third, to analyze Alex's budget, we called our Analyzed budget
function and passed in Alex's monthly income and the total expenses we obtained in the previous function call. Since the analyzed
budget function expects a list of expenses, we converted the integer
total expenses to a list. Finally, we displayed
Alex's budget analysis. Awesome. Now you've practiced creating and calling
user defined functions, along with learning several
other key functions concepts. Next, we will dive into
the topic of namespace and scope and get a
little more practice with user defined functions.
48. Namespace and Scope: Now that we've had some practice writing our own user
defined functions, let's revisit an issue that we briefly touched upon earlier. When we helped the architect
calculate the area of a building using the
rectangle area function, we noticed that the
area variable could not be accessed from outside the function
where it is defined. In this video, we'll explain
why we got that error. To do so, we must explore two
new programming concepts, name spaces and scope. These ideas build directly upon the notion of variable that
we have studied before. So let's begin by briefly
reviewing this notion. Let's begin with a basic
program that calculates the area of a rectangle
without using a function. This program first assigns values to several variables
representing the length, width, and measurement
units of the rectangle. Then it calculates
the rectangle's area and prints the result
with the proper unit. As you already know, when PyTon executes the first
lines of this program, four variables are created
and assigned values. However, there is more
happening behind the scenes. When PyTon executes
variable assignments, it adds the variable into a structure called
the global namespace. You can think of a namespace
as a labeled container that holds the names of variables and functions created
during execution, allowing PyTon to manage and
access them efficiently. In our rectangle area program, the global namespace act
as the primary container, holding all the variables
that we've created, length with unit and area. Variables stored in the
global name space are accessible anywhere during
a program's execution. This enables us to use them freely for calculations
and output. In a simple program
like this one, which does not use functions, it is sufficient to understand how the global namespace work. However, as programs
grow more complex, we often organize our
code into functions to improve readability
and reusability. The introduction of
user defined functions changes how variables are accessed and managed
in a program. Let's see how by tracing the
execution of this program, when the first line
of code is executed, the variable unit is
assigned the value feet. Because this assignment is performed within
the main program, the variable unit is starred in the global
namespace as before. In the following line of code, PTN encounters the definition of the rectangle area function. Upon execution, the
function's name is stored in the
global namespace. Since the rectangle
area function is now part of the global
namespace, this function, like the unit variable, can be accessed anywhere in the program for the
remainder of the execution. A first function call follows the definition
of the function. At the very beginning
of this function call, PyTon assigns the value 100 and 140 to the land and width
variables respectively. Okay. But where in the name space will PyTon
store these two variables? This is where things
get interesting. When variables are created
within a function, PyTon does not store them
inside the global namespace. No, instead, PTN
creates a new namespace associated with the
function called the functions local namespace. The functions local
namespace is where the variables length
and width are stored. As we'll shortly
see, this separation of name spaces helps prevent naming conflicts and allows functions to have their
own private variables. Once the arguments
have been assigned, PTN calculates the
area of the rectangle. Because Piton is currently executing the body
of the function, the private variables length
and width are accessible. The result of the
calculation is then assigned to the variable area. Now, because the assignment is performed in the body of the
rectangle area function, the variable area is also added to the
functions local namespace, and not the global namespace. This becomes important later. When executing the final
line of the function's body, PyTon prints the content of
the variables area and unit. Recall that variables
in the global namespace are accessible from
everywhere in the program, including during the
execution of a function call. Now that all the
lines of code in the function have been executed, the program wraps
up the execution of the function call by discarding the local name space along with its content and returns
to the main program. At this point, the program's
global name space only contains the variable unit and the function rectangle area. That's specifically why
in the previous video, we obtained an error
message when attempting to print the rectangles area
from outside the function. As you can see, at this point
in the code's execution, the variable area
has been discarded, so we can't use it. When our program executes
the second function call, Python repeats the
same steps as before. First, a new local
namespace is created. Next, the arguments are assigned to the
corresponding variables. The calculation is performed
and the output is printed. Finally, the local name space is again discarded. Awesome. Now that we have introduced
the concept of name spaces, let's bring in some
more terminology. Variables that are stored in the global name space are
called global variables. Variables stored in
a local name space are on the other hand,
called local variables. Because global variables are accessible everywhere
in a program, we say that they
have a global scope. On the other hand,
local variables are only accessible within the function in which
they are defined. So we say that they
have a local scope. The notions of namespaces
and scope are admittedly more abstract than the
other programming concepts we have covered so
far in this course. In the next video,
we'll try to make those notions more concrete by going through some examples.
49. Namespace and Scope - Guided Examples: At the end of day two
of their five day hike, Jamie and Pike come across a small rectangular
clearing in the forest. Jamie is considering
setting up camp there, but she worries that there will not be enough free space to relax once they pitch their
tent and build a campfire. Given the concern about space, Jamie asks Pike to
determine if the clearing will provide the 40 square
feet of free space they need. To answer Jamie's
question in BTon, we first create a function
that calculates the area of a rectangle given
its length and width. We can then use this function
to calculate the area of the clearing and
the area of the tent. Next, we create
another function that calculates the area of a
circle given its radius. We then call this function to calculate the area
of the campfire. Finally, from the clearing
area we calculated, we subtract the tent area and the campfire area to get the amount of free space
left and print the result. That's all good. But notice that we have used
the variable name area to store the results
of our calculations inside both functions. Can we really do that? Can the same variable
name be used inside two different functions
or could this create some sort of
conflict during execution? Let's trace the
program's execution to see if this creates an issue. When the first line
of code is executed, PyTon reads the definition of the rectangle area function and adds the function's name
to the global namespace. PyTon then reads the circle
area function definition and also adds it to
the global namespace. Following the definition
of our two functions, BTN moves to the first
rectangle area function call. As you already know, when the rectangle area
function is called, PTN creates a local name
space where the arguments ten and 12 are assigned to the parameters length
and width respectively. Moreover, during the
functions execution, Biton assigns the result
of the area calculation to the variable area in the
functions local name space. The function call
concludes by returning the value of the variable
area to the calling point. Since there is only
one area variable in any of the name spaces, there is no possible
confusion regarding which area variable
should be returned. Once the return statement
has been executed, all the variables in the rectangle area name
space are destroyed and a new global variable
clearing area is created to store the
function's return value. On the execution of the next rectangle
area function call, Biton creates a new
rectangle area namespace that contains the
function parameters. The area of the tent
is then calculated and stored in a
new area variable. Then Python returns the
value of the area variable. Since there is once again, only one area variable in
any of the name spaces, there is no possible confusion regarding which area
variable should be returned. So far, so good. When the function returns, all of the variables in the rectangle area
namespace are destroyed and a new global variable tent area is created to store the
function's return value. Finally, Piton calls
the circle area function to calculate the
area of the campfire. Here, a new local name space for a circle area function is created with the
perimeter radius. PyTon then calculates the
area of the circle and assigns it to a new
local variable area. When Pyton returns
the calculated area at the end of the
function's execution, there is once more, only one variable name area
in any of the name spaces. As a result, there is no possible confusion regarding which value should be
returned to the program. The bottom line here is this. When defining functions, we can reuse the same variable
names without issues. Local variables live within their function name space and die when the
execution completes. This guarantees that
naming conflict will not occur when we use the same variable names
in multiple functions. Note that this principle also
applies to parameter names. We can reuse parameter names
across multiple functions. In the exercises,
we will verify that reusing parameter names will not cause issues in our code. For the time being, just
take my word for it. Awesome. With that
observation behind us, let's finish tracing the code. When the circle area
function returns, its name space is destroyed, and the return
value is stored in the global variable
campfire area. Finally, using the
three area variables, PyTon calculates the free
space and prints the result. Great. If Jamie and Pike set up their tent and
campfire in this clearing, they will have almost 49
square feet of free space, which is more than enough. While they set up cam to unwind after a hard
day of hiking, we will work over time to deepen our understanding of
variable name conflicts. As we just saw,
different functions can use the same
local variable names without problems because
each function call creates its own namespace. However, we haven't
discussed what happens when a global variable has the same name as
a local variable. For example, let's rename the clearing area variable
to area in the main program. That area exists as both a
local and global variable, how will PyTn behave? To find out, let's trace
the execution of our code. Like before, PyTN
begins by reading the function
definitions and storing the function names in
the global namespace. Then it executes the
first function call, creating the rectangle
area, local namespace. Inside the rectangle
area function, PyTon calculates the area and stores the
calculation inside the local variable
area the value of the area variable is then returned where the
function was called. At this point, there is only one area variable in
any of the name spaces, so there is no
potential conflict. When the function returns, all of the variables in the rectangle area name
space are destroyed, and a new global variable area is created to store the
function's return value. Interesting, we now have a
global variable named area. I bet you can see where
things are going. On the execution of the next rectangle
area function call, PyTon creates a new
rectangle area namespace that contains the
function parameters. PyTon then calculates
the area and store the result of the calculation inside the local variable area. Let's pause here for a second
to examine the name spaces. Two variables named area now exist in different
name spaces, a local variable
containing the tense area calculated in the current
function call and a global variable containing the clearings area calculated in the previous function call. When asking PyTon
to return the value of area at the end of the
current function call, which of the two variables
will PyTon return? Since the same variable name is used to reference two
different values, PyTon needs a way to figure out which value
should be returned. In the Pyton language, the rule is to use the local version of the variable when there
is a potential conflict. In this example, it
means that PyTon will return the local
variable area created within the rectangle area function and not the global variable area we assign at the end of our
previous function call. When the functions
execution is completed, the local name
space is discarded. Then PyTon calls the
circle area function, and a new local
namespace is created. During the functions execution, Piton calculates the
campfire area and assigns the result to
the local variable area. Here again, there are two area variables
in the name space. One is local. The
other one is global. As a result, Pyton returns the local version of the area variable at the end
of the functions execution. When the function returns, all of the variables in the rectangle area name
space are destroyed and the value of the local
area variable is assigned to the Campfire
area global variable. In the next line of code, Pyton uses the variable area to calculate the
remaining free space. At that point, only
the global version of the area variable exists, and there is no ambiguity. Finally, PTN prints the
calculation result, which is identical to what we obtain in our first
rundown of the code. Over the last two videos, you have seen how PTN manages name spaces as it executes code. Distinguishing between the
global and local name spaces is critical when writing
user defined functions. In the following exercise, you'll get to
practice that skill.
50. Namespace and Scope - Exercise Solutions: This workbook, you trace through four different programs to
determine their output. Let's break down each
program to illustrate their namespaces and
understand how the logic, variables and functions interact to produce the final output. In exercise one, we recall that if a variable isn't
defined locally, Python will search the
global namespace to find it. To understand this
program's output, let's trace it and build
the namespace step by step. First, Python reads the
two variable assignments and the function definition, adding the names length, width, and calc wrecked area to
the global namespace. Next, Python executes the Calc wrecked
area function call, creating a local namespace. Within the function,
the variable width is added to the
local name space. When Python reaches the length
times width calculation, it must determine
which values to use. Bec a local width
variable does exist, Python uses this one instead
of the global width. However, since there is
no local length variable, Python expands its search to the global namespace
and finds it there. Remember, Python falls back to the global variable when no
local option is available. As a result, the calculation
uses length equals five, and width equals two, giving an area of ten. When the function returns, the local namespace
is destroyed and ten is passed back to the
call point and printed. In exercise two, we learned that function parameters act as local variables within
their respective functions. Even if different functions
use the same parameter names, it doesn't cause
any issues because each function has its own
independent local scope. To understand this
program's output, let's trace it and build
the namespace step by step. First, Python reads both
function definitions and adds them to the
global namespace. Next, Python executes the elk triangle
area function call. This creates a
local namespace for the function and adds the parameters base
and height to it. During the calculation,
only one base and one height variable exist
in this local name space. Since there is no conflict
with any other variable names, the area is calculated as one half times five times
three, resulting in 7.5. After the function returns, the local namespace
is destroyed, but the return value 7.5 is passed back to the main
program and displayed. Then Python executes the Calc
wret area function call, which also creates its
own local namespace and adds the parameters
base and height to it. As before, there is
only one base and one height variable in the
function's local scope. With no naming conflicts, the area is calculated as five times three resulting in 15. The value 15 is passed back to the main
program and displayed, and the functions
local name space is destroyed afterwards. In exercise three,
we learned that when a perimeter and a global
variable share the same name, Python will use the most local name within
the current scope. Let's trace the program to understand the
namespace in this case. First, Python reads the
global unit variable and the elk square area
function definition into the global namespace. Next, it executes the Calk
square area function call, creating the function's
local namespace and passing the values four and meters as arguments to the length and unit
parameters respectively. The function then
returns a string containing the squared
length and the unit. At this point, there
are two unit variables, one in the global namespace, and one in the functions
local namespace. Since Python always uses the most local variable when
there's a name in conflict, it selects the unit variable from the function's local scope, which has the value meters. As a result, when the
function returns, the output is 16 meters. In Exercise four,
we learned that conflicts can also arise
when a global variable, a function parameter, and a local variable
share the same name. In such cases, the most local
name is still always used. Let's confirm this by
tracing the program. As an exercise three,
Python first reads the global unit variable and the elk square area
function definition into the global namespace. Then it executes the Kelc
square area function call, creating the functions
local namespace and passing four and meters as arguments to the length
and unit parameters. Inside the function, the
unit variable is then reassigned to yards overriding the parameter value of meters. At this point, there's a
naming conflict between the local unit variable and
the global unit variable. However, as we learned
in exercise three, Python always uses the most
local version of a variable. In this case, since the local unit now
holds the value yards, that value is used when
constructing the return string. As a result, when the
function returns, the output is 16 yards. Awesome. Now you have a solid understanding of how namespaces and
scope work in Python. Now it's time to tackle the final core topic of this course modules
and libraries.
51. Modules and Libraries: In previous lectures,
we saw that when Bton's built in functions
fall short for a given task, we can always achieve
what we want by creating our own user
defined functions. That's great. But writing our own functions
is time consuming, and we can make mistakes. Thankfully, in many instances, there is another option. Indeed, PTN offers
a vast ecosystems of modules and libraries, offering pre written and tested code that can perform
a wide range of tasks. In this video, we'll learn
how to integrate and use these powerful PTN
libraries into our programs. We'll start slowly
by introducing the libraries
through an analogy. Imagine PyTn's built
in function as the books on your personal
bookshelf at home. These books, just like
built in functions are instantly accessible
but limited in number. When the book you need
can't be found at home, you may be able to find it by visiting your
municipal library. In our analogy, PyTon libraries act as the programming equivalent
of municipal libraries. They expand the set of available functions when PTon's built in functions fall short. PTN offers a vast
ecosystem of libraries, each serving different
programming needs. Among them, the PyTN
Standard Library stands out as one of
the most important. So that's where we'll begin
our exploration of libraries. Just as a municipal library
is organized into sections, each grouping books
of the same genre, the PyTN Standard Library
is organized into modules, each grouping related functions. For instance, the
Bton Standard Library has a math module that
contains functions performing mathematical
operations such as taking the square root or
the logarithm of a number. The library also includes
a random module, which provides functions for
generating random numbers, which is useful for simulations
and a statistics module, which provides functions
for calculating common statistics like
the mean and the median. However, just as the books at the municipal library require more effort to access than
the ones you have at home, functions in the PTN
standard library are not as readily available as
PTNs built in functions. To use a function from a module
of the standard library, we must first check
out the function from the library by importing
it into our program. For example, to import the
square root function, SQRT, from the MAT module, we write from MAT Import square root. In that statement,
the fra Mat part instructs Piton that we want to retrieve a function
from the MT module. The import SQRT part specifies which function we want to
import from that module. Once imported, we can use the square root function as many times as we
need in our program, just like any built in function. Besides the square
root function, the MT module contains many
other helpful functions. For example, the PD function calculates the product of
the elements in a list. This function could
be helpful to calculate the cumulative
growth rate of an economy over the
last five years given a list of
annual growth rate. Of course, using the Pd function is not necessary in this case. We could find the answer
by using a four loop, iterating over the
elements of the list to calculate the cumulative
product of the growth rates. But why reinvent the wheel when importing the prod
function is so simple? Besides the MT module, the PyTN Standard library contains many more
useful modules, some of which you'll
explore in the exercises. Unfortunately, we
can't do justice to all the functions available in the PyTN Standard
library in this course. There are simply too many. For that reason, on the Git
up page of this course, there is a link to the PTN
Standard Library documentation where you'll find a list of functions included
in that module. Feel free to consult this resource whenever
you need to find a specific function or
explore the capabilities of a particular module in the
PyTN Standard Library. However, as
comprehensive as it is, the PTN Standard Library
also has limits. Just as your municipal library doesn't contain all the
books ever written, the PTN Standard Library
does not include functions for every
possible programming needs. Fortunately, there
are other libraries called external libraries that can help in those situations. External libraries have been created by the PTN
community to address specific programming
needs ranging from data analysis and machine
learning to web development, data visualization, and more. To gain access to these
external libraries, you must first get a library
card by installing them. In an interactive notebook
environment like Google Colab, getting this library
card can be done using PTNS preferred
installer program, also known as PIP, to install an external library
type exclamation point, PIP install, followed by the name of the library you want to install in a code cell. This line of code instructs PyTN to install the
MTPltLib library, a popular tool for data
visualization in PTN. It's worth noting that
Google Colab comes pre equipped with many
popular library cards. For instance, Matpltib is one of those pre installed
libraries in Colab, as the requirement already
satisfied output message indicates when we run the code. Re installing a pre installed
library does no harm, but it is not necessary
and it can be skipped. After installing a library, we can use the dot notation to import specific functions
into our program. Here, we import the
plot function from the PyPlot module in
the MatplotLib library. We should know that
when we imported the PD function from the MAT module of the
PyTon Standard Library, we did not specify
the library's name. The BTN Standard Library
is the exception. For this library and
this library alone, we do not need to specify the library's name before
accessing its module. For all other libraries,
including MatplotLib, we must specify the library name before accessing its modules. Once a function from an external library
has been imported, it can be used in the program just like any other function. For example, let's say we
have a list of numbers, X that we want to plot against some other list of number, y? This can be done with a
call of the plot function, passing X and Y as arguments. Executing the cell, we
get a graph of our data. Awesome. But at this stage, you may be wondering, how do I determine if there is an external library
that can help me solve a given
programming task? Since thousands of
external libraries are currently out there and more are continuously
being introduced, memorizing the list of available libraries
is not the answer. Instead, the best
way to determine if there's an external
library that can help you is a Google search or a query to your favorite large language
model like Chat GPT. Once you have identified a library that might be
useful for your task, you should consult its
documentation to find the specific module where the functions you're
interested in are located. A Google search is generally all that's needed to
find the documentation. In the exercises and
the final project, you will explore some of PTN's most popular
external libraries in detail and become familiar
with this discovery process. To sum up, when PyTN's built in function and its standard
library falls short, external libraries provide a large number of
additional functionalities. However, to access
these functionalities, we must first install
the library containing the desired function and then import it into
our PTN program. The vast collection of
libraries available in PTN is one of the greatest
strengths of the language. By leveraging the
global knowledge of the PyTon community, user like you can stand on
the shoulders of giant and tackle complex tasks with
remarkable efficiency. But don't take my word for it. The best way to
appreciate the power of PyTon libraries is to
see them in action. In the next video, we'll explore together
a few use cases.
52. Modules and Libraries - Guided Examples: Since we last caught up
with Jamie and Pike, they have successfully completed their challenging five day hike. Back home, Jamie feels a sense of pride
and accomplishment. She's eager to share her adventure with friends
and family and decides that a visual representation of our daily progress would
help tell the story. Although Pike isn't naturally
skilled at drawing, he knows exactly where to find the right tools to create
the figure that Jamie wants. Just as Pike needs to rely on external tools
to draw a chart, we'll rely on external libraries to create a nice
figure in PyTon. More specifically, we'll
use the Matpltib library. As we mentioned in
a previous video, the Matpltib library is
already installed in Colab, so we can skip installation
in this workbook. As we have seen,
the plot function of the Pilot module
can create figures, so let's import that function. We'll also import
the show function to instruct PyTon to
display the plot we create. While you can import
the show function by writing a separate
import statement like this, there is a more
concise way to do it. Indeed, PTN allows us to
import multiple functions from the same module by listing the functions to import
after the import keyword. Awesome. Let's now create lists that contain the
information we want to plot. The first list we create
contains the days of the hike, and the second list contains the corresponding miles
hiked on each of these days. Then we call the plot function
with the days list as the X axis value and the Mils hiked list as the Y axis values. Finally, we instruct
Bton to display the figure by calling
the show function. Executing the cell, we obtain a plot of the miles
hiked on each day. This is fine, but
you will surely agree with me that this
plot is pretty bare bones. In particular,
there is no title, and the axes are not
labeled. Let's fix this. To add a title and
axis labels to a plot, we need to import the functions, title, X label, and Y label. Then we call each function passing the desired title
or label as the argument. Neat. When we rerun our code, we obtain a graph with a descriptive title and
properly labeled axis. But these are far from the only customization
options we have available. For example, let's say that Jamie would like to
plot a horizontal line on the graph to represent the average daily mile she
hiked over the five days. This can be done in two steps
using the axHline function. In the first step, we calculate the average
daily miles hiked. In the second step, we pass the average as the argument of the
AxHline function. After running our code, we obtain an updated
plot in which the average daily miles are represented by a
horizontal line. With this new line
added to the graph, it is now easy to tell on which days Jamie hiked
more than the average. And as a result, our graph is becoming more and
more informative. Nevertheless, we have numerous
additional options at our disposal to enhance the visual appeal and
effectiveness of our graph. For example, by default, MTLtib represents data as a thin blue line without markers for individual
data points. However, we can enhance
the visibility of our data by specifying a marker style in
the plot function. Passing the string, Oh, tells PyTon to add
circular markers around the data points while maintaining the connecting
lines between them. Running the code, we observe
that datapoint markers have been added
accordingly. That's great. Let's now make our graph
more interesting by using different colors of lines and styles for each data series. For instance, let's
say that we want our average mile line to
be dashed and orange. This can be done
using AxH lines, color and line style
keyword arguments. Executing the cell
updates our plot with the latest changes.
Pretty right. As a final touch, we'll add
a legend to our figure. To do that, we'll need
the legend function. In my opinion, the most
convenient way to use the legend function is to first create labels for each
line in our graph. Then just call the legend
function without any argument. By default, the legend function will use the provided labels
to construct the legend. Wonderful. Now, that's a
professional looking graph. As you can see,
the Piplot module provides powerful data
visualization functionalities. In fact, the Piplot
module contains so many functions
that importing them all one by one can
be cumbersome. Fortunately, PyTon provides
a more efficient approach. That is, we can import the entire module at once
using the following syntax. Import Matplotlib dot Pilot. When we import the
entire module this way, we can access the modules function by using
the dot notation. As you can see, repeatedly typing the full module
name can be conversome. Thus, to streamline our code, we often use aliases when
importing entire modules. We create an alias by
adding the keyword as followed by a short
descriptive label after the import statement. For the Pipelot module, a common alias is PLT. Defining an alias this
way allows us to use the shorter PLT instead of matplotlib dot PiePlt
throughout our code. Awesome. Jamie is thrilled with the graph
that Pike plotted. She posts it on social media
and receives tons of likes. As we prepare to tackle the capstone project
of this course, we'll bid farewell to
Jamie and Pike for now. See you on the trails,
Jamie and Pike. As you can see, Matpltlib
is a powerful library. We'll explore it
in greater details in the exercise workbooks. Besides Mat Plutlb, the
exercise workbooks will also let you explore several other very useful
PyTon libraries.
53. Python Standard Library - Exercise Solutions: This workbook, you
explored the math random and statistics modules from the Python
Standard Library. Let's go over the solutions. In exercise one, we
investigated the math module. In part A, we were
given a list of population densities
and asked to calculate the square root
of each value in the list. To do this, we apply the Math
modules SQRT function and add ten to each element using either a four loop or
a list comprehension. Both methods give us the protected area sizes calculated from the number
of deer in each herd, but the list comprehension
is more concise. In Part B, we were asked to
calculate the growth rate of the frog population using the provided growth
equation and inputs. To implement this
equation in Python, we use the EXP and log
functions from the math module. The EXP function calculates the natural exponential raising E to the power of its argument, while the log function computes the natural logarithm
when called without specifying a different
base as an argument. We compute the frog
populations weekly growth rate to be 111.47%. In Part C, we were given a list of daily food
requirements for several species and
asked to calculate their total food needs over
120 day winter season. Crucially, before
calculating the total intake over the hundred and 20 days, we needed to round
each value up since the emergency food is only
available in whole units. To do this, we apply the SEL function
from the math module to each element in the
daily food intake list using a list comprehension. Next, we multiply
each rounded value by 120 days to get the total food required
for the winter season. As you can see, failing to
round up the daily intakes before multiplying leads to
noticeably different totals. Alternatively, we can achieve the same outcome using a four loop instead of
a list comprehension. In Exercise two, we used the statistics module
to calculate the mean, median, and mode of the moose
population counts given. The statistics module does
all the heavy lifting for us by providing the mean
median and mode functions. We just pass the
population counts list to each of the functions
and output the results. Lastly, in exercise three, we tackled the random module. In part A, we were asked to use the random modules
uniform function to model the potential remaining
lifespan of each rabbit we are tracking and calculate
its total projected lifespan. We start by using a
list comprehension with the uniform function, which generates a float
between two specified values. In our example, given a rabbit
that is 8-years-old today, our list comprehension
will generate a random float 0-12 minus eight, which is four to model its
remaining potential lifespan. Using the list comprehension, we generate projected lifespans for each rabbit in
our rabbit ages list. Then to calculate the total
lifespan for each rabbit, we use another list comprehension
and the ZIP function. The ZIP function pairs each rabbit's age with its corresponding projected
remaining lifespan. We add each rabbit's
current age to its projected remaining lifespan to compute its total
projected lifespan. Lastly, we use a four loop
to output the results. In Part B, we were given the probabilities of several weather events and
asked to model the growth of the
rabbit population over the next 12 months to forecast its size
one year from now. We used the random modules
choices function for this. We pass in the
population growth rates as the values to be
randomly chosen from, the weather probabilities as the weights the
function should use, and K equals 12, which tells the
function to choose 12 random population
growth rates. This call results in a list of 12 simulated population
growth rates, one for each of the
next 12 months. Then using a four loop, we apply these rates to the rabbit population
cumulatively growing it over the
next 12 months. Finally, we output the forecasted rabbit population
for one year from now. In Part C, we enhanced
our simulation to output multiple 12 month
population forecasts at once. We embed our code from Part B into a four loop
that runs ten times, appending the result of each simulation to the
simulated Pops list. When the loop is done running, we output the list of ten
simulated population forecasts. In Part D, we use the statistics module
to analyze the list of ten population
projections we generated in Part C. Specifically, we compute the mean
standard deviation and quartiles of our data. Like an exercise two,
the statistics module provides all the
necessary functions, so we simply call the mean standard deviation
and quantiles functions. By default, the quantiles
function computes quartiles, but it also allows you to adjust the N parameter to divide the data into more
sections if needed. Lastly, in part E, we used the random
modules CD function to make our random
values reproducible. The seed needs to be set before generating
any random values. This ensures that all
values produced by the choices function are random but can be
reproduced in future runs. Setting a seed is commonly
used for testing or debugging code that involves
using random values. Great. As you have seen, the Python Standard Library
is a powerful set of built in tools that can aid in solving many
types of problems. But as we mentioned
in previous videos, there are many other
external libraries provided by the Python community that
are available for us to use. In the next few videos, you will have the opportunity to explore several of
these libraries.
54. Matplotlib - Exericse Solution: This workbook, you
learned how to create several basic types of charts and graphs using the MatplotLib library's
PyPlot module. Let's break down the solutions. In exercise one, we
were given a list of sales data and used a line
chart to visualize it. MatplotLib allows us to create
a line chart by calling the plot function with a
list of X coordinates here, the range of days and a list of Y coordinates,
the sales data. Additionally, we can customize the line chart by
specifying a color, marker style, line
width, and marker size. Then we add a title, X label, and Y label by calling the
appropriate functions. Finally, we add a grid
and display the plot. In exercise two, we were
given lists of categories and sales data and
created a bar chart showing the sales breakdown
of the three categories. To do this, we used the
bar function and passed the goods categories as the X variable and the sales
data as the Y variable. Additionally, we also passed in a list of colors to customize the charts bars and added a title and labels
for the X and Y axis. Then to add the sales data amounts to the top of each bar, we used a four loop and
matplot Libs text function. This function takes
X and Y coordinates for the labels as the
first two arguments, followed by the text to display and the
horizontal alignment. Finally, we display the chart. In exercise three, we were given the percentage
of customers in different age groups and generated a pie chart
to visualize the data. We created a pie chart using
Matplotlibs Pi function, passing in the list
of percentages as the data and the age
groups list as the labels. Additionally, the
Pi function takes the slice percentage
label format and list containing wedge colors
as keyword arguments. Next, we add a title and
legend to our chart. The legend function
takes the data to display as arbitrary
arguments and other formatting
features like the title and location as arbitrary
keyword arguments. Lastly, we display the chart
with the show function. Finally, in exercise four, we were given data
about advertising spend and resulting sales and created a scatter plot to visualize the relationship
between the two variables. To do this, we called
the scatter function passing in the advertising
spend and sales data. We customized the color and size of our scattered dots with two additional
arguments and added a Title X and Y
labels to the plot. Lastly, we displayed the
plot with the show function. Great. You now have
experience creating line, bar, and pie charts, as well as scatter
plots using MTPotib. However, we've only just begun
to explore its potential. Matplotlib is an essential tool for data visualization
in Python, and I encourage you
to continue exploring its features to enhance your problem solving
capabilities in the future.
55. Pandas - Exercise Solution: This workbook, you explored the Pandas library to analyze
and manipulate flight data. Let's discuss the solutions. In Exercise one, Part A, we loaded the given flight
data into a data frame. To do this, we simply passed our data into the
dataframe function. Then when we output our data, it is displayed as a well
formatted data frame. In Part B, we needed to display the first two flights in
our flight info data frame. DataFrames have a
method called head, which takes an integer number of rows to display
as an argument. The output of this method
call with the argument two is the first two rows of
our flight info data frame. In Part C, we needed to generate summary statistics about
our flight info data frame. DataFrames provide a
method called describe, which calculates several
useful statistics such as mean and
standard deviation. Moving to exercise two, we learned how to
filter our data frame based on certain conditions. In Part A, we created a data frame containing only
flights traveling to LAX. To do this, we first used a conditional expression
that identified which values in the
destination column of our data frame
were equal to LAX. This created a series of Booleans which we use to
filter our data frame. The resulting data
frame contains only the flights
destined for LAX. In Part B, we filtered our
flight info data frame to display only flights with an arrival delay greater
than 20 minutes. As in Part A, we specified
an expression to filter out the flights with
arrival delays that are less than or
equal to 20 minutes. The resulting data
frame contains only flights with delays
longer than 20 minutes. In exercise three, we performed calculations using
data frame columns. In part A, we added a new total delay
column to track the total arrival and departure
delays for each flight. To create this column, we summed the values in the departure delay and
arrival delay columns and told Python to store that data in a new column called total Delay. Displaying the
updated data frame, we see that our new total
delay column was added. In Part B, we calculated the total average delay
across all flights. Since we already calculated the total delay
column in Part A, we simply call the
Panda's mean method on the total delay column. The result tells us that the average total delay is 35
minutes across all flights. In Part C, we calculated the average total delay
for flights going to ORD. To do this, we first filtered the flight info data frame
like we did in exercise two. Then we apply the mean method to the total delay column of the data frame containing the
flights destined for ORD. We find the average
delay for flights to RD is 46.25 minutes. Lastly, in Exercise four, we learned how to
sort data frames. In part A, we sorted the flight info data frame by total delay in
descending order. Pandas provides the sort values
method into which we pass the column to sort by and whether the order should be
ascending or descending. This method call produces
a data frame where the flights are sorted by total delay in descending order. Finally, in Part B, we sort our flight
info data frame by departure delay in
ascending order. Like in Part A, we use the sort values method and specify the column to sort
by and ascending order. This method call outputs a
data frame where the flights are sorted by departure
delay in ascending order. Awesome. Pandas is a
powerful Python library for data manipulation
and analysis, providing flexible
data structures like data frames to efficiently
handle structured data. You can use it in
your own projects to simplify data cleaning,
transformation, and visualization, as well as wrangling large datasets
and performing analytics.
56. Language Translator App - Project Introduction: Grats. After lots of hard work, you've made it to
the course project. Your task now is to build a language translation
application that can translate text between
various languages and manage a collection
of favorite translations. You will need to use
concepts like while loops, libraries, dictionaries,
conditionals, and more. In this project module, you will find detailed
text instructions that guide you through
building your application. Additionally, we have provided the text of a sample interaction with the program to give you a better idea of how the menus
and functionalities work. In the remainder of this video, I'll do a quick demo of how the final
application will work. When a user launches
your application, they are presented with a
menu of translation options. Option one is Quick Translate. This option translates
a word that the user inputs using the default
from and to languages. Option two is print
available languages. This displays a list of all available languages in the translator library,
which you must install. Option three is change
default languages. This feature allows the user to set default languages
for translation, specifying both the source and target languages
for future use. The initial default languages are set to English and Spanish, but users can choose any
languages they prefer. Option four is translate
and detect source language. Here, the user only needs to specify the target language
and enter a phrase. The application will
automatically detect the source language and translate
the phrase accordingly. Option five is translate
and specify languages. This option prompts the user
to select both the source and target languages before entering a phrase to translate. And finally, option six
is managed favorites. This takes the user to
a sub menu where they can manage a dictionary of
their favorite translations. If we choose option one, the application uses the
default source language, English, and the default
target language, Spanish to translate
the phrase we enter. If we choose option two,
the application lists all of the languages available through the Google
Translator module. Each language is accompanied by an abbreviation that can be used in place of the
full language name. Next, let's select
Option four and enter the target language along with the
word to translate. The application will
automatically detect the source language and
perform the translation. Finally, if we
choose option six, we enter a sub menu for managing favorite translations where four additional
options are available. Choosing Option one will
allow us to add a favorite. We can enter the favorite phrase along with the source
and target languages. Then this information will be saved to the
favorites dictionary. Users can add as many
favorites as they like. Using option four, we can view
our favorites dictionary. Here, we see that all of
the translations have been saved along with their
source and target languages. If we wish to return to the translator options,
we enter zero. And we can quit the program altogether by
entering zero again. Great. Now it's time for
you to start the project. Remember, detailed step
by step instructions are available in this module as
well as a sample interaction. Good luck and happy programming.
57. Language Translator App - Project Solution: Welcome to the Language
Translators Solutions video. If you're here because
you're feeling stuck on a step, don't worry. We'll walk through the
solution one step at a time. You can follow along until you reach the part that's
giving you trouble. And if you're here
because you've already finished the
project, congrats. You've put in a
lot of hard work. So now let's dive in
and check your answers. In step one, we start by
initializing the project. The first thing we need to do is make a copy of the
provided notebook. Next, we install the Deep
Translator library by simply running the command
PIP install Deep Translator. In step A, we write the
display main menu function, which takes the default from and to languages
as arguments. The print statements display
the program's main menu. In step two B, we define
two global variables, default from and default two. These will be used for the
quick translation feature. The default from variable
sets the source language while the default two variable sets the
default target language. In step two C, we update
the main program to call the display main menu
function passing the global variables we defined in step two B as arguments. In step three A, we request the user's translator
option choice with a call to the
input function. In step three B, we create
a conditional block, which will decide which action to take based on
the user's input. Eventually, we will replace each print statement with the action's corresponding
function call. But for now, we will use print statements
as placeholders. If a user selects an
option that doesn't exist, we display an error message. In step four A, we define the global variable that we use to control the
main program loop. Then in step four B, we create the main program loop. To allow the user to make as many translations
as they want, we use a wile loop controlled by the global variable
we set earlier. We then move the code that
displays the main menu, captures the user's choice, and determines the
appropriate action inside of the while loop. Finally, we remove the
print statement for option zero and instead set the should continue
variable to false. Now, when the user enters
zero, the program will exit. In step five A, we write
the translate function. This function will
take three parameters, the source language,
the target language, and the text to translate. Inside the function, we use the Google Translator module and its translate method to
handle this translation. Now, it might seem a
bit strange to call a method like translate on what looks like
to be a function, but that's because
Google Translate is actually creating an object. The concept of an object is an object oriented programming
notion that we haven't covered in this course.
But don't worry. Understanding object
oriented programming isn't necessary for using the library for simple translations
like we're doing here. We simply return the result of the translate method which
contains the translated text. In step five B, we write the function
called quick Translate. The function takes the source
and target languages as parameters and then prompts the user to enter the text
they wish to translate. To perform the translation, we call the translate
function created earlier, passing in the source language, target language, and the
user's text as arguments. Finally, we capture
the translated text that's returned by the translate
function and display it. In step five C, we update the main program's
conditional block to call the quick Translate function when the user
selects option one. We pass in the default from and to language
variables as arguments. So the only input the
user needs to provide for this option is the text
they want to translate. In step six A, we write
a function to print the available languages in
the Google Translator module. This function doesn't
take any parameters. Inside the function, we call
the G supported languages method and request the results to be returned as a dictionary. Then we loop through
the dictionary, printing each language along with its corresponding
abbreviation. In step six B, we update the conditional
block in the main program to call the print
available languages function when option
two is selected. In step seven A, we
write a function to set the default languages
that the program will use during the
quick translate feature. This function doesn't
take any parameters. Inside the function, we
prompt the user to enter a new default
source language and then a new default
target language. After that, we print a
confirmation message letting the user know that the languages were
successfully updated. Finally, we return both
the from and to languages. In step seven B, we update the
conditional block in the main program to call the set default
Languages function. Since this function returns the new source and target
languages as a tuple, we unpack these values directly into the global default
language variables. In step eight A, we write the translate detect
source lang function, which translates a phrase into a specified target language while automatically detecting
the source language. This function doesn't
take any parameters. Inside the function, we prompt the user to enter
the target language. Then we call the quick
translate function that we defined earlier to
handle the translation. To automatically detect
the source language, we pass the string auto
as the first argument. The user provided
target language is passed as the
second argument. Since the quick translate
function both prompts the user for input and
outputs the translated text, we don't need to duplicate these actions in this function. In step eight B, we update
the conditional block in the main program to call the translate detect
source language function. In step nine A, we write the final translation function,
translate specify angs. This function
requires the user to specify both the source
and target languages. Once those are provided, it calls the quick
Translate function, which prompts the
user for the text to translate and then
performs the translation. In step nine B, we update
the conditional block in the main program to call the Translate specify
Lang's function. In step ten A, we write the function to display
the favorites menu. This function doesn't take any inputs and simply displays
the menu to the user. In step ten B, we write the function that manages
the favorites dictionary. This function takes the favorites
dictionary as an input. Inside the function, we define a new loop control variable
to manage a wile loop, allowing the users
to interact with the favorite's menu as
many times as they like. Within the loop, we display the favorites menu and prompt the user to
choose an option. Since we have not yet
written these functions, we use print statements
as placeholders. If the user enters zero, we set the loop control
variable to false, which exits the favorites
management loop and returns to the
main program menu. In step ten C, we
start by defining a new global variable to
store the favors dictionary. Making the favorites dictionary a global variable ensures that it won't reset each time the user accesses
the favorites menu. We also update the main program's conditional
block to call the managed favorites function passing in the Global
Favorites dictionary. Finally, we update the
Global Favorites dictionary with the managed favorite
functions return value. In step 11 A, we write the add
favorites function. First, this function will prompt the user to enter the text
they wish to favorite. Next, we ask the user to
input the source language of the original text followed by the target language that they
wish to translate it into. Then we call the
translate function defined in step five A to
handle the translation, passing in the user's text, source language, and target
language as arguments. The translation result is captured in the
translation variable. We then create a new
entry in the Favorites dictionary using the text
to favorite as the key, and a dictionary containing
the source language, target language, and
translated text as the value. Finally, we output a confirmation message
letting the user know that their favorite
has been successfully added to the dictionary
and return the dictionary. In step 11 B, we update the conditional block
in the manage favorites function to execute the add
favorite's functionality if the user chooses option one. We also update the favorites dictionary with the return
value of the function call. In step 12 A, we write the
remove favorite function, which takes the favorites
dictionary as a parameter. First, the function prompts the user to enter the
favorite they wish to remove. Next, we check if the user's input exists in
the favorites dictionary. If it does, we remove the entry and print a
confirmation message. If the input does not exist, we display an error
message instead. Finally, we return the
Favorites dictionary. In step 12 B, we update the conditional block in
the managed favorites function to execute the
remove favorite functionality if the user chooses option two. In Step 13 A, we write the edit
favorite function. First, the function prompts the user to input the
favorite they want to edit. Next, it checks if the favorite
exists in the dictionary. If it does, the
user is asked for a new target language to
translate the favorite into. Then we call the
translate function passing in the original
source language, the new target language, and the text to translate. This returns the original phrase translated into
the new language. We update the favorites dictionary with the new
target language and the updated translation followed by printing a
confirmation message. If the user entered a
favorite that doesn't exist, we display an error message. Finally, we return the
favorites dictionary. In step 13 B, we update the conditional block
in the manage favorites function to execute the
edit favorite functionality if the user chooses
option three. In step 14 A, we write a function to print the current favorites
dictionary. First, the function checks if there are any entries
in the dictionary. If there are, we
use a four loop to iterate over all the keys and
values in the dictionary, printing them in a clear
and well formatted string. If the dictionary is empty, we simply display
an error message. In step 14 B, we update the conditional block in the managed
favorites function to execute the print
favorite's functionality if the user chooses option four. Finally, in Step 15, we make our program
more robust by handling errors that may occur
from invalid user input. We start by modifying the
main loop of our program. When we prompt the
user for input, we wrap the code that casts the input into an integer
inside a triblock. If the user enters non numeric
text and the cast fails, we catch the resulting
value error in the except block where we display an informative
error message to the user. We also use the continue
keyword to skip the rest of the current iteration
and start the next one, ensuring the program
doesn't crash. If the cast is successful, the usblock executes and the final formatted
string is printed. We apply the same error
handling approach to the managed favorites
functions loop. Here, we wrap the user input
cast inside a Triblock. If the cast fails, we catch the error in
the accept block, display an error message, and move to the next iteration. If it succeeds, the se
block executes as expected. Great. You've now
seen how to build a language translation app using the Deep
Translator library, complete with features
like quick translations, customizable default
languages, and error handling. Feel free to refine the app
further and make it your own. Keep exploring and building. There's always more to learn.