Scope is a fancy way of saying we're going to use this variable,
or we're going to use this function.
And I think the best way to learn about scope is to really
just experience it, because I find trying to describe it
in words doesn't actually make sense.
And when I was first learning scope, someone tried describing it
to me, and I was like, "I don't get it.
Like I can use a variable in one place, but not another place",
which is effectively, yeah, that's what it is,
but there are rules behind it.
So let's go ahead and create an example here.
We've got 'language = "Python", and then if I do 'def
change_language(): language = "JavaScript"'.
And let's return that 'language' in this function, and we 'print(
language)'. This is a really good example of scope.
So we've originally set it to be "Python",
we've got this function in here called 'change_language()', and
it's reassigning the exact same variable here to be called "JavaScript".
So when I run this cell, do you think this is
going to be "Python", or do you think this is going to be "JavaScript"?
[no audio]
Let's go ahead and run this cell, and we're going to see
that it's "Python".
Now, the reason for this is because this 'language = "Python"',
'language' variable is in a higher scope, and the "JavaScript"
variable is in a function.
So essentially, the "JavaScript" variable isn't allowed to
be accessed outside of this function at all.
This is called scope, where we have sure, we have a variable
called 'language' here and here.
But inside of this function, Python is saying, "Hey, there
is another variable in here called 'language', and I'm going
to use this one in here", and it's going to be completely
unaware of this other one for the time being.
Now what happens if I actually run this function?
So I'm going to run 'change_language', and I try to figure out
what 'language' is again.
So I've run this language.
It has now said, okay, 'language = "JavaScript", and
it returned that 'language', as we can see here.
So now that it's been overwritten, should 'language' be "JavaScript",
or should it be "Python",
because we executed some code that overwrote that variable.
Well, if we run the cell, we're still going to see that it's still "Python".
So Python uses this thing called the LEGB rule.
'L' stands for 'Local'.
So names assigned in any way with a function like 'def' or
'lambda'. So it's going to look for a variable in here, and then
it's going to look for, enclosed function locals, that's the
'E', and that's names in local scope and any enclosing functions
or functions that are outside of functions,
because in Python, we can nest functions inside of other
functions. We'll touch on that a little bit later.
Then the 'G' is 'Global'.
So the global module that's outside of here. And then the
built-in Python library, that's the 'B'.
And that means if there is a variable that Python is already
using, then it's going to look for that.
It's one of those keywords, such as the word 'for', or 'while',
or 'True' or 'False', those are all keywords,
and so Python is going to try to reserve those.
You can overwrite them, but please don't, because you're
going to cause a lot of problems if you overwrite them.
So that's why we try not to overwrite keyword variables that
Python already gives us, or keywords that Python gives us.
So a good way to look at this
is really Python is going to say, "Okay, there's language
= "Python"."
There's a function in here, but it doesn't actually execute
that function right away.
It just says, because this code is basically touching this
line here that is going to register it, but it isn't actually
executed. But when you do execute, this function, it's going
to look from the inside to the outside.
So it's going to look for a 'language' in here called "JavaScript",
and if that does not exist, it's going to then use the 'language'
up here called "Python".
So let's go ahead, comment this line out, and let's rerun
this. Okay, it still says, "Python", but when we run
'change_language()', it's going to 'return language'.
Now, this used to say "JavaScript", but this now says "Python".
'language', here for all intents of purposes, does not exist.
And so because it couldn't find a variable in here called 'language',
this just simply didn't exist,
it looked outside of its own scope.
And so it looked up here for the word 'language', or the variable
'language', and used that one.
Now, let's create a little more complicated example, and
I don't expect you to totally know what's going on here,
but we are going to take a look at nested functions.
So if I have 'name = "Kalob"', this is a global variable.
If I then create a function called 'greeting', and I put the
'name' in here as "Zephyr", this is an 'enclosing variable'.
And if I put another function in here 'def say_hello', and
this 'name = "Henry", this one is local.
And so what we can say, because this is a function inside of a function,
we can run this function inside of the 'greeting' function,
and then we can run 'greeting' on its own.
So let's go ahead and run 'greeting'.
And before I do that, let's take a look at what we think
is going to happen here.
So I'm going to run 'greeting'.
'name' is already defined outside of it.
Then we're defining 'name' inside of this to be 'name = "Zephyr"'.
And inside of here,
the 'name = "Henry"'.
And actually, what we should do is print this out.
'print("Name is ", name)'.
There we go. That's actually going to work for us.
And so remember, it's going to go from the inside to the outside.
And so we're running 'greeting',
but inside of 'greeting' it's running 'say_hello',
so it's running another function in here, and that 'name' is
currently "Henry".
And so if we have this correct, this should say 'Name is Henry",
as we expect.
But let's comment this out,
so that 'name' effectively no longer exists inside of the
'say_hello' function.
We run this again, and it's going to say "Zephyr", because
I can't find it in here, but it's going to look just outside of its function.
Now, let's say 'name' doesn't exist inside of 'greeting'.
Well, because it's looking for a 'name' here, it doesn't exist;
it's looking for a 'name' in here, also doesn't exist;
it's now going to look outside of all of the functions in
the global scope.
Let's run this cell and run that once more, and we're going
to see the "Name is Kalob".
Now, what this means, is you can create a function in here
with absolutely no variables,
and as long as there is a variable that it's using that's
outside of it, you can use it.
Now, that sounds a little crazy.
But let's say the 'website = "pythonforverybody.com",
and we have a new function in here called 'def get_website'.
We can 'return website'.
And when we run 'get_website', this will return 'pythonforeverybody.com',
despite the fact that there is no variable
in here, and that's because it exists just outside of the
function scope.
But we can now say 'website = 'nothing because Kalob
ruined this''.
[no audio]
It now exists in here, so it exists in two places, but the
function is going to look inside of itself
first. Says, "Oh, yep.
Okay, there is actually a variable called website.
So let's use that one".
But again, if that variable didn't exist in here, it would
look in the global scope.
Now, that's actually sort of a really bad way of using a
function, and that can get very, very confusing for other
people who are looking at your code.
So typically we avoid that, and we just put the 'website'
in here. So the 'website' could be "pythonforeverybody.com"
as a default, and that would be fine.
We can get rid of this, or we could overwrite this with, "anything
else", assuming I could spell. There we go.
"anything else".
And so this is a much better way than leveraging the Python
scope. Now, if you come from JavaScript, it's not uncommon
for JavaScript to leverage its own scope like that.
But in Python, we try really hard not to do that.
We try to explicitly pass in data into our functions just
so we know exactly what's going on in here.
And the reason for that is if I just gave you this piece
of code here, that's a 'def
get_website', and 'return website',
but you didn't know where 'website' came from.
Maybe you're looking at a file that has 2,000 lines of code,
and you can't seem to find this variable, that's going to
be very confusing because you're going to look at this, and say,
"Yep, this is a function, and it's returning a variable called website.
But where is website?"
And if you have to stop and ask yourself, where is that,
then that's probably a good case for using a function argument
or a parameter.
[no audio]