Instructor: Up to this point,
we've learned about a few ways to organize our Python code.
The first thing we did,
well, we just wrote Python in a file,
and that organizes it, right?
Our entire code has been so far on one single file.
So that was one way that we organized our code.
Next, we learned about functions.
And functions were used as a way for us to not write code
that we repeat over and over.
We could write functions that we can use anywhere we want
in our file
so that we can call these functions over and over,
and we can name the functions appropriately
so that our code makes sense.
And then we learned about classes, right?
These blueprints that we can create objects from.
We can instantiate new Python data types
beyond the ones that they just gave us, right?
Instead of just having dictionaries and lists,
we can create our own custom ones.
Our own lists may be that have extra features,
and we're able to use classes to organize our code
to box them up and give each class a certain method
and attribute that packages it nicely for us to use.
We also learned about functional programming
and how unlike, let's say, object oriented programming
where we see a lot of classes.
With functional programming,
we just use a lot of functions, a lot of pure functions.
And we have data that we just pass into those functions.
And we organize things into small little pieces.
All of these things were meant for us
to keep our code clean,
make our code more maintainable,
thus keeping our code organized.
Because as we write more lines of code,
it gets harder and harder to keep everything in your head.
If other people join your team to work on your project,
they need an easy way to figure out how things are working.
But we still have a problem.
And that problem is that everything is contained
in this one file.
All the functions, all the classes we've been writing
has been on just one dot py file.
But in real life, this isn't the case.
We have a lot more code.
And we can't just have one file with millions line of code.
So, how do we stay organized?
Well, if we had multiple files of Python like this,
because our project is getting bigger and bigger.
would this work,
is there a way for us to link all of these files together?
As a matter of fact, there is,
and this is very common practice all across industry.
And we call this way of organizing code modules.
And modules are simply, well, these files,
each one of these files, each dot py file is a module.
And by building these modules,
kind of like we built different functions,
kind of like we built different classes.
Because in inside of these files, we can have classes,
we can have functions, but we can also have different files.
So, a layer higher to divide up our code.
And in this section,
we're gonna learn all about modules and try to master it
and see how we can write organized code.
Let's have a look.
You can see over here,
if I click on files in our repo, we have a main.py.
And every time I click run, this file gotta run.
But what if we have more files?
What if I add another file here?
and we'll call it utility.py?
So, based on what I just told you,
these two things are what?
They're modules, right?
Maine.py is a module.
Utility.py is a module.
And when writing modules,
we use the same principles as variables in Python,
which is snake case.
That is if there's spaces,
we use underscore everything is lowercase letter.
So, how do we divide up these modules?
And this comes with practice.
When you're just beginning, it's hard to say,
"Hey, what goes into what file?
What goes into what file?"
But it's similar to classes, right?
Similar to functions.
We wanna divide up our code into chunks that make sense.
Again, let's say we're working at Netflix.
We might have a file dedicated to videos.
We might have another file or module
dedicated to the login of a user,
maybe another file dedicated to analytics
and figuring it out recommendations for users.
We wanna group these classes and functions together
inside of a file that makes sense.
Now, one of the most common ways to use a module
is something like a utility.
Let's say we wanna create a utility module,
that is a module that has a lot of,
well, kind of like a tool belt,
very simple functions that we can use
all across our project,
because we can imagine here having multiple files.
So, let's create a very simple example.
I'm going to say a multiply function exists here,
and this takes a num1 and num2.
And in here we're simply going to return num1 times num2,
a very simple function.
And once again, we'll also have a divide function.
And yes, this is kind of useless
because we can just use the plus or to divide operant
in Python.
But stick with me here.
I'm trying to show you an example.
All right, so num2,
I'm going to return num1 divided by num2.
Nice and simple.
So, this is our utility module
that has all these functions for us.
Now, notice here that we're actually not doing anything
in this file.
I'm simply defining functions,
but I'm not running any of the functions.
But let's say we have this utility module
and I wanna use it in my main.py file.
How would we go about doing this?
Well, the way we communicate
between these two files is quite simple.
All we need to do is use the import command,
we import and then give it the file name
that we wanna import.
What do we wanna import?
We wanna import utility, just like that.
And notice that I'm not adding the dot py
because we assume that whatever we're gonna import
is going to be a Python file.
So, we don't need to do that, just the name, just like that.
Now, let's print utility here.
If I run this,
wow, do you see that?
We have module utility from,
and then this is a file path that this website generates
for us.
So, it doesn't really matter.
Now, there's a few things that happened here.
One is that we generated this pycache folder,
underscore, underscore pycache.
And oh, boy, what is this gibberish?
Hmm, this is pretty confusing, right?
Well, this pycache is created
every time we run a file with, let's say, import statements.
So, when we're using modules.
You see what pycache does is when we click run,
the interpreter is going to create this pycache folder
and it's going to say, "Hey, I'm running this file,
this one main.py file."
Anything that main.py file imports,
let's say utility in our case, I'm going to cache it.
So, see how here it says .pyc.
This is because it's using the C Python interpreter.
Remember, this is the C Python,
which is the interpreter written in C.
So, this is actually a compiled file
so that next time I click run here on my main.py,
nothing changes.
Because what's going to happen is,
instead of loading up utility.py,
it's going to load this compiled version of utility
because nothing has changed in utility.py.
And this makes things faster
when I try to run main.py again.
That's what caching is.
Caching is, hey, I'm going to remember this,
and this is the compiled version
so I don't have to go through their compilation step again.
But notice that the main.py file does not get compiled
because, well, we run it every time.
Now, if we change the utility function
to not have the divide in there, I click run.
And you don't notice it here.
But this has now been rerun
because we have a different file.
You see that we have multiply here, but not divide.
So, let's bring back divide again.
Go back to here, click run.
And there you go.
We have divide here too now.
But this is something that we don't touch.
This just comes underneath the hood
with any editor that we use.
And in a few videos,
we're gonna show you how this also happens
when we use something like Pi Chart.
This is just something that editors allow us to do
just so our programs can run faster.
So, I now have access.
Let's make this a little bit smaller.
I now have access to utility.
And here's the interesting part.
If I dot here, look at that.
I have access to divide and multiply
so that I can multiply numbers,
let's say two and three, click run.
And I am able to use the utility module in my main file.
Very, very cool.
If I do divide and I click run, I can use this as well.
Very, very cool.
And I can import as many times as I want.
If I had a different file in here,
and I wanna import another thing
let's say there is a utility to file.
Well, I can import that,
and import as many things as I want
and use them across my files.
How cool is that?
So now we have a way to organize our code
and have all these files communicate together,
because in real life, we have big projects.
And these big projects are going to be worked on
by different teams, different programmers.
And we need a way to work with all these files.
And by using the import statements between modules,
we're able to use functionality
just like we were able to use the functionality
that functions provided us between different files.
And most of the time, if you're working at a company,
the first couple of lines on a dot py file
are usually import statements
because usually, you're communicating with other files.
Let's learn some more in the next video.