In this video we’re going to take a real-world
formula, for the number of layers of puff
pastry, as a use case for making a small program
where the user will input some data, the program
will make a calculation with that data, and
then print out the result to our user.
And in doing so we will walk through several
skills through this video, defining a function,
storing data in variables, getting an input
from a user and converting that input to an
integer which is then going to be stored into
the variable, and then printing the finished
data back to our user using an f-string.
Then we’ll close with making our program
a little more airtight with try and except
blocks to prevent errors from crashing our
program.
But first a little story, so I was eating
a puff pastry the other day, and, naturally,
whenever doing anything and I hope you do
this too, I looked it up on Wikipedia, I took
a look at the article for puff pastry while
I was eating a puff pastry, and as I'm scrolling
through the article I find this unexpected
gem.
The number of layers in puff pastry is calculated
with the formula l = (f+1) all to the power
of n, where l is the number of finished layers,
f is the number of folds in a single folding
move, and n is the number of times the folding
move is repeated.
I’m no pastry chef, but I thought this would
be an interesting, real-world mathematical
formula to play around with a bit in Python.
We could make a program that will let our
user check the number of folds and the number
of times the folding move is repeated, so
the number of folding moves so to speak, and
then lo and behold, our user will immediately
learn how many layers his or her puff pastry
will have based on those inputs.
And so as our first step, before we start
writing out the actual code itself, let’s
make another comment, and you see this little
sharp symbol, or the pound or hash symbol,
is just our way of writing something that's
just for the human reader, it's the same thing
that I did with these headings, the computer's
just going to ignore it, but it is good to
just kind of think it through, and the way
you would do that is with a comment.
And I looked at this formula from the Wikipedia
article and one thing that sprung to mind
is “l” is not going to be a good variable.
It might be all well and good for writing
this formula mathematically, but the letter
l, it looks too much like the number 1, so
I wouldn't want to use the letter l here,
and in fact we could use letters l, f, and
n, but those aren’t very descriptive, so
instead let’s write out as a comment the
formula that we ultimately want to achieve,
using the variables that we're ultimately
going to use, in a way that's a little more
readable.
And let's call it layers equals folds plus
one to the power of - this star star is to
the power of - num_moves.
And this is the same thing, this is the same
exact thing we had here, but just with some
variables that are a little bit more descriptive
and better for what we're going to be doing.
So what are we going to do here?
Well there's three variables, and they're
called layers, folds, and num_moves.
The user is going to give us the number of
folds that he or she wants to use, the number
of moves that they're going to make, and our
program will take these inputs, add one to
the number of folds, and then raise the whole
thing to the power of number of moves, and
the result is going to be stored inside a
variable called layers.
And then it's going to print the number of
layers for the user to see with some nice
little phrase that will say "the number of
layers is" whatever it is, and that's where
our f-string will come in as we'll see.
So let's get this into a form that will work
with Python, and we'll break it down step-by-step.
There’s a few different ways to tackle this
same problem, but what we're going to do in
this video is we're going to make a function
that will do all of these steps, and then
do what's called "calling the function," we'll
call the function so we'll put everything
- you can think of a function as kind of a
block of code that you define with instructions
for what you want it to do once executed,
and then can execute that function later,
whenever and wherever in your program that
you want.
So in Python, there are a lot of built-in
functions, you've certainly seen these even
in your very introductory tutorials.
For example, if you type print(“Hi”) that
is a function called print, these parentheses
are what shows that it's a function, and then
in this instance you don't need to define
it, it already is - it comes built in to Python.
What it's going to do is it's going to give
you this output of "Hi" if you were to run
it - there it is, so you see it says "Hi."
Ok, and so that's fine, that's a pre-written
function, but you can also define your own
function, and have it do whatever you like.
So, if I wanted a function called num_layers()
to calculate the number of layers of puff
pastry, I can have one, so long as I define
what it does first.
So you see, if I just write num_layers() with
parentheses and then I try running this program,
it's going to throw me an error, the name
num_layers is not defined.
Fair enough, it's not, I didn't do anything,
I just pulled this out of a hat, right?
So I do need to define the function in order
for this to do anything, and more specifically,
I need to define it in a way where it’s
going to carry out all of the things that
I want it to do to get the number of folds
and moves from the user, plug it all in to
our formula, store that calculation inside
a variable called layers, and then print out
to the user the number of layers.
To define a function, we use the keyword def,
d-e-f, then space and then the name of our
function, which as you can see down here is
going to be num_layers().
Ok, and so what we have is def num_layers()
with the parentheses to show it’s a function
– there won’t be anything inside the parentheses
here – sometimes there will be, but not
for this example, but even so, you will need
the parentheses just in order to show Python
it’s dealing with a function.
And then a colon.
Ok, so this is def, space, name of the function,
parentheses, colon.
And then I'm going to hit enter because I'm
on a PC, or return if you're on a Mac, and
it will go to the next line.
Notice that when I hit enter to go to the
next line, the IDE that I’m using, PyCharm,
automatically indents, but if you’re just
doing this on just a notepad or something,
make sure you indent yourself so you have
a little indentation here, because everything
that's in this indented block is going to
be within the definition of num_layers(),
within the definition of our function num_layers().
You can either do that with four spaces or
with a tab, but make sure you do one or the
other throughout your program, either four
spaces or a tab.
But honestly if you find yourself in that
situation, just get an IDE that will do it
for you, it will make your life a lot easier,
something like PyCharm is free, and it will
automatically indent as soon as you do that.
Ok, so, everything else within the definition
of our function is going to come afterwards,
it will all be on indented lines.
Let’s give some thought about what we’ll
need in order to get the outcome that we want.
Ok, well, we’ll need the three variables
of course, and in order to make a variable,
you type the name of the variable, which we'll
just use the same names that we have here.
So folds would be one of our variables, for
example, with an equals sign - and then everything
after this equals sign on the same line is
going to be what gets stored inside the variable.
But let's write these out first, and then
we'll store something inside them.
Ok, so you see here, we are making each of
these a variable, and then we have an equals
sign, it's not a mathematical equals sign,
but rather an indication that we are going
to be storing some data inside these variables.
And so what are we going to store?
We're going to store the user's input for
each of folds and num_moves, and then store
the calculated result inside the variable
layers.
So I want to explain a little bit about how
to get a user's input because there are a
few steps and there is one little tricky thing
in this example which is that we're going
to want to get a user's input and then convert
it to something that we can do math with,
some kind of number.
So let's go through how to get a user’s
input, and what I'm going to do is I'm going
to comment out each of these items, and so
you see I just put in this little comment
sign so that they're still written in but
the computer's just going to ignore them,
and then go a few lines down just to show
you the example of what to do in terms of
getting the user's input.
To get input from a user you use a function
called input() with parentheses.
And to show you how input() works, what we're
going to do is we're going to make a variable,
and let's call it inputted_data, equals sign,
and then after that equals sign we'll use
the function input() and inside these parentheses,
in quotes, we put a prompt for the user to
see.
And that's what the user's going to see, and
then whatever the user types in response to
that prompt is what's going to ultimately
be stored in our variable.
So let's do this, let's do "Input some data:
" Ok, and that's what the user's going to
see, and that information is going to be stored
inside the variable inputted_data, so what
we're going to do just to show you is we're
going to then print the variable, so what
we're going to do is we're going to have the
user input the data, we're going to print
whatever it inputted, and we're also going
to print the type of the inputted data, just
to show you the type of data that gets stored
when the user inputs something with this input
function because it will be very important
for later.
So when we run that, and let's make it a little
bigger, so now you see we run it and the user
is prompted to input some data, and let's
do the number 3. and hit enter since I'm on
a PC or return on a Mac, and so you see the
user inputted some data, which was 3, and
then it did the next line which is to print
that inputted data, also a 3, but when we
printed the type you see it's class 'str'?
That means it's a string, and a string you
can think of as kind of like plain text, the
computer is not considering this to be a number.
A number could be something like an integer,
which is like a whole number, or a float,
which is like a number with decimals after
it, it's not coming up as an integer or a
float, it's coming up as a string, which is
kind of just like plain text, and you can't
do math with it.
So you see how this is going to become an
issue when we want to have our user input
some data up here and then do a mathematical
calculation?
You can't do it just with input but the good
news is that you can convert this input into
an integer or a float.
So if you wanted to convert it to a float,
you can do float with parentheses around this
input.
So it will say "Input some data: " and then
the user will input that data, that will then
be converted into a float, and then be stored
inside your variable which will then be printed
and it will also print the type.
So now let's try this again - input some data,
and let's do 3, and you see it prints it out
as 3.0 because it's a float so it's always
going to have some kind of decimal point even
if mathematically it's otherwise an integer,
it's still going to have that decimal point
because it is, as you see, a float.
And the same is true for integers, you could
do int(), i-n-t, and it will then, if you
do a 3, now it's just a 3, no point zero,
and it is class 'int' that is to say, it is
an integer.
Ok, so you see, it inputted some data - it
prompted you to input some data, you did input
the data, you inputted a 3, it converted that
into an integer, and then stored that in the
variable inputted_data, you printed it, and
then you printed its type, which is an integer.
All right, and the float or the integer are
great for our use case, because we want to
use some kind of mathematical formula, which
you can do with floats or integers, you cannot
do just with a string.
So let's delete this out, and let's delete
out our comments, so now we have def num_layers():
and underneath that we have the variables
we'd like to use, folds, num_moves, and layers.
So let's start with folds.
We want the user to input the number of folds.
Well recall that here you could write input()
and then put the prompt inside these parentheses
in quotation marks and let's make our prompt
Number of folds: colon space, note I am adding
a space here deliberately so that it's a little
cleaner once it prints out the prompt it's
going to have that space afterwards and you
won't have your user running right up to this
colon.
Ok. that’s not quite good enough here, remember,
we want our program to do some math.
And just this input function on its own will
take what the user types in and consider it
to be a string.
We saw before if the user types in a 3, it
won't treat it as a number it will treat it
as plain text and you can't do math with plain
text.
So we have to decide whether we want to convert
our string into a float or an integer as we
saw before.
And that will depend on your situation – but
thinking through our goal here, which is our
layers, folds, number of moves for a puff
pastry, for a real-world puff pastry, we would
only need integers here for these values – you
can’t really have half a finished layer,
or a third of a fold, or repeat a folding
move 3.2394 times or what have you.
Your really could only do these things in
whole numbers.
So we are going to want to use integers here.
Certainly many other times you'll want to
use floats, but in this case let's go ahead
and use integers.
So what we’ll do is we’ll take this input(“Number
of folds: “) line and write int() after
it, and then we'll close out these parentheses
and so, this integer function takes what's
going to be a string and then, as we saw before,
convert it into an integer.
So even if the user typed in 3, and then it's
a string 3, it will convert it to an integer
3.
And if the user types something that can't
be converted into an integer, than we'll have
a big problem on our hands, but we'll address
that later.
Ok, then we’ll do just the same thing for
the number of moves, we’ll do int() then
inside those parentheses, input() and then
inside those parentheses the prompt, in quotation
marks, “Number of moves: “ or something.
Ok, and that will store an integer that is
the number of times the folding move is repeated,
or we just kind of shortened it to number
of moves.
Then finally, what do we store inside our
variable layers?
Well, the formula that will calculate the
number of layers, of course!
And so let’s do layers is (folds + 1) to
the power of number of moves.
Recall again that this star star is the way
you write “raised to the power of” in
Python.
Ok, so it's folds plus one to the power of
num_moves and you don't need spaces after
this plus but I'm just going to do it to make
it look a little neater.
And now we have everything we need to calculate
the number of layers, and indeed if we were
to run this function the computer would do
this calculation and would store our number
of layers inside this variable “layers.”
But our goal is to let the user know what
the result is, the user is going to be asking
"hey, what is the number of layers?"
And if our computer knows but our user doesn't,
that's not good enough.
So we want to output something for the user
to see, and to do that we can use the built-in
print() function.
And inside these parentheses we can print
out whatever we want our user to see, so as
promised I'm going to show you something very
special, and relatively new, the f string,
also known as the “formatted string literal.”
So inside these parentheses you’re going
to want some kind of statement that says “Number
of layers in your pastry: ” and then display
the number of layers and maybe some flavor
text afterwards like “Sounds delicious.”
How do we do that?
When we have a value in a variable that we
want to go inside of our string, we can do
an f-string, so we'll type the letter f first,
and you can actually use a capital or a lowercase
letter f here, and then we'll put what we
want to write in quotes, so let’s do f”Your
pastry will have: “ and then put curly brackets
and inside those curly brackets the name of
the variable you that want to print out here,
which in our case is {layers}.
And then after that you can just write Sounds
delicious.”
Ok, notice the curly brackets and in fact
this entire statement is all inside the quotation
marks.
And notice the f that preceded these quotation
marks to show that we're going to be using
an f-string.
The f-string, the beauty of it is that you
can put in these curly brackets and the name
of the variable and it will print out the
value that's stored inside of that variable.
Looks great.
And that’s the whole function.
And recall that we have this here, num_layers()
with parentheses, it's the name of the function
with parentheses that comes after the function's
definition, it's not indented.
That's critical.
If we don't have this, if we just had the
definition and we didn't have this, then the
function wouldn't run.
Nowhere would we be telling the program to
actually run the function.
This num_layers() here with the parentheses
is our way of telling our computer when and
where to actually execute all of this code
that we're storing in the definition of our
function here.
So, let’s run it.
And let's bring it up a little bit, and make
it a little bigger.
Ok, so Number of folds:
Well, how many folds do we want to give it?
Let’s take a look at our snip here, which
gave an example, from the Wikipedia article,
of twice folding with four moves which should
give us 81 layers if everything worked out
right in our program.
Let’s give that a go.
So, number of folds would be 2
And the number of moves would be 4
And it says our puff pastry will have 81.
Sounds delicious.
Well, our pastry will have 81 [laughing] as
you see it's a good decision to run this to
test this out because our pastry will have
81 what?
It will have 81 layers, so let's type in the
word layers here and try that again.
Make it a little bigger.
Number of folds, it was 2, and number of moves
was 4.
Much better.
Your pastry will have: 81 layers.
Sounds delicious.
So that's all well and good, and it worked,
we got the right result, it's consistent with
our example, so that's nice, but what if our
user put in something that wasn't just some
integer?
What if our user did something, not even trying
to mess it up on purpose, what if our user
did something that could make perfect sense,
but just won't work?
Like typing in the word two here.
So, Number of folds: two -v and you see that's
not some - our user isn't going out on a limb
here, it's a perfectly ordinary thing for
the user to think could work, so let's try
it.
Doesn't work though, when we hit enter we
get “ValueError” – why?
Well, recall we're converting whatever we
put into this input from a string to an integer.
And that word two, written out, Python is
not going to consider that to be the same
thing as the numeral two.
And it's just going to say “hey, I can’t
convert these letters into an integer, this
isn't going to work, ValueError, can't do
it.”
And you get the same result if you want to
do something like one and a half folds, which
remember when we were thinking do we want
a float, do we want an integer, well you can't
really do one and a half folds, well what
if your user says "give me 1 and a half folds"?
That's also going to be a ValueError.
And why is this giving a ValueError when normally
you can convert a float to an integer no problem,
it will just round it down, it's not usually
an issue?
Well, I can show you that in the console here.
It is true that if you were to just do int(1.5)
it will just round it down to 1 and it would
convert it to an integer.
But that’s not what’s happening here – remember,
when you use input() it actually takes the
user’s input as a string.
So what you're really asking it is not this
question, you're asking it what's the integer
of the string 1.5, the plain text 1.5, convert
that into an integer, it won't do it, it gives
you a ValueError, ok.
So you get this same error whether you type
in text or numbers, you get ValueError, right?
And so that's no good, your user is doing
something that's perfectly natural for a user
to want to try and it's crashing your program.
So how do we prevent your user from crashing
the program on purpose or accidentally?
That is where try and except statements can
help us out.
Right underneath [def] num_layers() here,
right underneath the definition of num_layers()
here, we're going to type the word try like
so, with a lowercase t and a colon.
And then everything underneath that, that
we want to try, which is all this, should
be indented.
Ok, now, instead of just instructing the program
to just do all these things, we are instead
instructing the program to just try to do
all of these things.
Just to try it.
And as Homer Simpson aptly put it, “trying
is the first step towards failure.”
And that’s ok, that trying is the first
step towards failure, because we just need
an instruction for what should happen if what
we try were to fail, that is to say, if there
was an error.
And that’s where the “except” statement
comes in.
At the same level of indentation as try, you
can put in an except.
So - having trouble with my mouse here - so
you have try, and then you have the word except
and notice the lowercase e and then you write
the name of the name of the error that we
are going to anticipate could happen, which
in our case as you recall was a ValueError,
let's just copy it and paste it right in there.
Ok, so except ValueError and add a colon and
then on the next line, indented, we can put
what exactly it is we want to happen in the
event the program encounters this ValueError.
And in this case, what might be a good outcome
is if the program explained to our user what
went wrong, and gave our user an opportunity
to try everything all over again.
So let’s have a print statement that's something
like "Integers only, please.
Try again."
And then let's go ahead and put the name of
the function with the parentheses afterwards,
which is just going to re-do the function
from scratch.
Note that in theory you could just write except
with a colon here and it do every error under
the sun, but that’s not a best practice,
you want to identify a particular error to
the extent possible – and in our case we
know that we’re looking to prevent a ValueError,
so we specify ValueError here, except ValueError:
print("Integers only, please.
Try again.")
and then re-run the function from the top.
So let’s test it out.
So now, when the user types in here some gobbledegook,
it's going to say "Integers only, please.
Try again."
It gives the user another chance.
And if the user tries two, it will say "Integers
only, please.
Try again."
Otherwise though, if the user does input integers,
as we want it to, then it will still work.
So let's try another example, and let's just
try the other example from our snip here.
You see Julia Child recommends 73 layers for
this and then 729 layers for this other dish,
I'm not going to attempt to pronounce it,
I am not a French speaker, but if we have
729 layers, which is 3 to the sixth, well
we can think of that, that's going to be an
f of 2 and an n of 6, right?
And that should give us 729 layers.
Let's try it out.
So we have number of folds of 2 number of
moves of 6, and it does, that gives us 729
layers.
And so for that particular type of pastry,
that is exactly what we wanted.
And if you were interested in a purely theoretical
puff pastry, and you wanted to do something
crazy with a lot of, oh, let's do 40 and - I
don't want to make it too big - let's do like
12 or something, and then it's going to have
some absurdly large number of layers, that
you wouldn't have in a real life puff pastry,
though it does sound very delicious, but you
could use this formula to extrapolate out
how many layers you could get with these folds
and these moves.
And so that's an example of where using programming
for a problem like this can be a very powerful
and important tool because you can kind of
model out the number of theoretical layers
that you could have.
Ok, and so there’s a lot more ways we could
beef up our program further.
You could also use a library called SymPy
to solve the equation for any of these variables,
right, so you could actually solve it for
n here or solve it for f, for folds, and have
the user input the other variables and get
the number of folds, the number of moves and
the number of layers for example, and I considered
making that part of this video but the video
was already going on a little long, but I
will put in the top right-hand corner a little
flag for a different video I made, Solving
Equations with SymPy which should be popping
up on the screen now, and that will go through
the theory of how to do that.
But other than that, I will leave you with
some more food for thought so to speak: it
would not make much sense to allow your user
to input a negative number into this formula.
You couldn't have negative 4 layers of pastry,
for example.
But you see, if I run this program, and if
I type in say negative 4 folds and then 3
moves, then all of a sudden I'm dealing with
negative 27 layers, and that's fine if your
goal was to extrapolate this mathematically,
but if you're just making a program where
someone wants to calculate how many layers
they're going to have in their puff pastry
[laughing] in the real world then it's one
thing to solve the formula but the real world
application is broken.
So the question that I'm going to leave you
with is how would you embellish this program
to prevent your user from inputting a negative
number?
Give it a shot in the comments section, there's
a few different things that would work so
don't be discouraged from giving an answer
even if someone else has already answered.
And of course any other embellishments or
improvements to make to this program, to make
it better, there's many many things in this
program that can be improved, it is of course
a simple program the real goal of which is
not to make an app that will actually make
this tool but rather to give a real-world
formula that can walk through these different
skills, so if you were to make this into more
of an app, how would you improve it?
Let us know that in the comments as well.
But that is where we will end today's lesson
which took a real-world formula and made a
program to apply that formula with input from
a user, and we covered how to define and run
a function, store information in variables,
get input from the user and convert it to
an integer, and how to use an f-string to
add variables to your strings, and finally
how to use try and except statements to hopefully
prevent an error from crashing your program.
We got through a lot so if you found value
in this it would mean really a lot to me if
you gave this video a like, and of course
I want to thank you very much for watching.
