Python Tutorial: Variable Scope - Understanding the LEGB rule and global/nonlocal statements

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey there how's it going everybody in this video we're going to be learning about variable scope in Python now understanding how the scope works is one of the more important concepts when working with the language because it's something that we're going to need to understand in just about every program that we write and understanding this also helps a lot when a variable may not have the value that we expected and we need to debug our code now if you don't know what I mean by variable scope now this is what determines where our variables can be accessed from within the program and what values those variables hold in different contexts so let's go ahead and look at some examples to get a better understanding of this so there's a common abbreviation for understanding the scoping rules within Python and that abbreviation is le g/b and this stands for local enclosing global and built-in now the local is which are variables defined within a function now in closing our variables in the local scope of enclosing functions and I'm going to go over examples of all these in just a second and a global are variables defined at the top level of a module or explicitly declared global using the global keyword and the built-ins are just names that are pre assigned in Python now the reason that the abbreviation is in this order is because this is the order that determines what a variable is assigned to so Python first checks the variables in the local scope and the enclosing scope and the global and then lastly the built-ins now we're going to look at all these in this video but instead of going in this exact order let's first start off with the global and local scope because these are probably the most commonly confused so let's say that I have a python module here where i simply set a variable x equal to a string global x and let me go ahead and just make this text a little bit bigger here okay now the variable X here is a global variable because it is in the main body of our file so now let's make a function here and I'll just call this test and within test I'm going to create a variable Y and I'm going to set this equal to the string local Y now this Y variable here is a local variable and it's local to this test function so if I were to print out why and then outside of this function run that function now you can see at the bottom here that prints out local Y so Python use that le GB rule when I print it out that Y variable and it said okay so first I'm going to check if I have Y and my local scope which our variables that are defined within the function and it found that local Y variable and printed it out so now within this test function I'm going to comment out that print Y and instead I'm going to also print X here now I'm printing X from within the test function so let's try to imagine what's going on here if I do this so if I go ahead and run this then you can see that even though we're within our test function it's still printed out that global X and the reason that it printed out global X is because it said okay do I have an X variable in my local scope which means that it's defined within this test function so it doesn't so now that it doesn't find it there it says do I have anything in my enclosing scope and we haven't gone over enclosing scope yet but we will in just a minute but I'll just tell you that it doesn't find an X and then enclosing scope either and then it checks if it has an X in its global scope and it does so it prints out the value that it found in that global scope which was global X but this doesn't go both ways though so for example if I come down here after my test function and I say print Y and run this now you can see that we got an error here and it says that name Y is not fine now if you're new to Python then you might think while I ran the test function here which should have set that Y variable and now I'm printing the Y variable here but the Y variable doesn't live outside of that test function when we print this Y variable out here it doesn't find a Y variable and it's local scope enclosing scope global or built-in so then it throws that name error okay so now instead of printing this Y from outside the test function now let's print that X variable and let me save that and run it so now you can see that sees that X global variable from within the test function and from without okay so now within the test function here let's change this Y variable here from Y to X and inside here I'm going to say local X and I'm going to save that okay so now before I run this it might not be obvious what this will print out so let's go ahead and run it so when I run that you can see that it ran the test function here came in and printed out this local X and then this it comes out and prints this X after the test function and it prints a global X now some people might think that the global X variable would have been overwritten here within the test function but that's not what happened so this just creates a local X variable here that lives only within this function and anything outside of that local scope still sees the global X variable okay but what if we actually wanted to set a new value for that global X variable from within this test function now to do this we can explicitly tell Python that the X variable we want to work with is the global X variable and to do this at the top we can just say global X and now it knows that we're working with that global X variable so now if I rerun this then you can see that it ran this test function came in and said that we're working with this global X variable set that the local x printed that out which was local X and since we explicitly told Python that we wanted to change that global X variable when we printed it even outside the function it still printed out this local x string now having this string set to local X is a little bit misleading now because that's no longer just in the local scope it's now in the global scope now one thing about this global statement is that we don't even have to have a global X variable defined before we set it here within our function so if I come up here and I comment out this global X variable and then rerun this code then you can see when we set this global X within the test function even though it didn't exist up here that it was still able to find that variable when we printed it out down here at the bottom now that only works when we're set that as a global variable so for example if I come in here and comment out that global X now we're just setting that locally so now if I run that then you can see that it printed out that local X from within the test function but this print statement outside of the test function threw an error because that global variable is no longer set now a lot of the times it can be tempting to learn something new and then overuse it I wanted to show you the global statement so that you know what it does and how to use it but honestly I don't think I've ever had the need to use this myself and if you find yourself using it often then you're probably doing something wrong so using the local scope of a function makes it easier to understand and easier to work with so you can imagine how difficult it would be to maintain our code if you use these global statements and had to worry about variables and your functions overriding values outside of that function so with the local scope being self-contained it allows us to not have to worry about what's going on outside of our function so I wanted to show you how the global statement works but be careful not to overuse it okay so now I'm going to go ahead and get rid of this global X statement here okay so now all of us have most likely seen functions that take arguments so let me add an argument here to this test function and I'll just call this variable Z now Z is going to be a local variable within this test function also so it's not going to exist outside of that function either it's just like when we set our local X variable within this function the only difference is that as a function parameter it can now be assigned values that are passed into our function so for example when I call my test function down here now I'm going to pass in local Z this string and that's going to set that local variable Z equal to this local Z string and so now within that function instead of printing out this X variable I'm going to print out Z and I'm just going to comment out this outside print statement here now if I run this then you can see that we passed in that local Z string when we see here it first looked in its local scope and Z is in its local scope and it found it there so it printed out that locals e-string and just to show you what it does if we try to print that outside of that function here I'm going to change this with print Z and if I run that and you can see that we got our name err name Z is not defined and that's because that sea variable is only local to that test function so now go ahead and comment out that and rerun it okay so now let's take a look at the built in scope now this one is pretty easy to understand because it's just names that are pre assigned in Python so for example min is a built-in function in Python that finds the smallest value of an iterable so for example I can use min by saying M equals min and I can pass in an iterable so in this case I'll just pass in 5 1 4 2 3 and now I'm just going to print M below here and let me comment out where I'm running that test function now if I run that then you can see that it prints out 1 because 1 is the smallest value in that interval now we were able to use min here because it's a built-in function in Python so if we'd like to view the variables that are within the built-in scope then we can simply say import built-ins and then after we import that then I can just print out e I are on that built-ins module now dir just gets a list of the attributes of a given object so if I run that and then let me drag this up a little bit here you can see that it returns all of the built-ins here a lot of these are exceptions and error names then if we scroll down here then you can see some others that were more used to so we have like print and min and Max and int and list and range and a few others that you're probably familiar with now one thing that you want to be careful with as far as built-ins go is accidentally overriding them so this isn't something that Python prevents us from doing now there's reasons for this but basically they're just trusting us with having the power to do that so for example if I was to create a min function here so let me comment out that printed built-ins there so if I was to create a min function here and then I'm just going to put in a pass statement there so now before I run this I'm just going to comment out where I use that built-in min function here so now I'm going to run this and you can see that I don't get any errors but now if I try to use that built-in min function that worked just a second ago so I'm going to uncomment out that code and run that and you can see that it gets an error saying that men doesn't or min takes zero positional arguments but one was given now the reason for that is when we ran this min function here Python found our min function in the global scope before it fell back to the built-in scope so you have to be careful with that so if I change the name of my global min function here to something like my men and rerun that code then that now you can see that it works again because now it doesn't find men in that global scope and instead uses the built-in a min function just like we expected okay so now we're going to take a look at the e part of that le GB rule and that stands for enclosing now before we do that let me go ahead and clean up some of this other code here so I'm just going to comment out everything except for that global X and that print X there now the reason that we saved the enclosing scope for last is because it's easier to understand once we understand the local and global scope so the enclosing scope has to do with nested functions so let's say for example that I have a function within a function so I'm just going to say I'm going to make a function call outer here and within here I'm going to set an X variable equal to outer X and now I'm going to have a nested function so within the outer function I'm going to call this function inner and within inner I'm going to have another X variable and I'm going to set this equal to the string enter X and now I'm going to print out that X variable from within the inner function and now I'm going to run that inner function and now I'm going to print out the X variable from within the outer function and now to run all of this I can run that outer function in the global scope area so now I'm going to go ahead and run that okay so I know that there's a good bit going on there so let's go ahead and walk through this so we have our outer function here that we ran so we came in here and we set our local X variable now this variable is local to our outer function and now we come in here and run our inner function and within our inner function we set this X variable and this X variable is local to our inner function and then we print that X variable now it uses our rule le GB so it looked if it had any local X variables and it does it has this inner X here and that's why it printed out enter X here because that is in the local scope and then we printed out X in our outer function here and it looked if it had any local X variables and it does it has this outer X local variable and it printed out outer X here so now let's comment out where we set our X variable within our inner function so now if I rerun this and you can see that it printed out outer X both times and this is what the enclosing scope is so when we got to the point within our inner function where we printed out this X it first checked if it had any X variables local to that inner func and it doesn't because we just commented it out so then it checks if it has an X variable and the local scope of any enclosing functions so that's why it's called the enclosing scope so now we're looking in the local scope of any enclosing functions so our enclosure closing function here is the outer function and we do have an X variable in the local scope of that enclosing function so that's why it printed out outer X so you can see that that's kind of similar to our global and local scope example except now we're inside functions the same concept kind of applies when we set X and our inner function it doesn't affect the X variable in the outer function and just like with our global and local scopes if I come out here and comment out this outer X and then uncomment out that inner X and save that and run that then we get an error because this printed out X within our inner function because it has that local X variable within the inner function then when we try to print it outside of that function it checked its local scope but that's commented out and then it's enclosing scope which it doesn't have any enclosing functions and then global which there's no global x function and then built-ins so it threw an error there ok so now let's go ahead and set that back to how it was where we comment out that inner x and uncomment out that outer x and rerun that okay so when we looked at our global and local variables I showed you how you could use that global statement in order to explicitly tell Python that you wanted to work with the global X variable so you may be wondering if there's a way that you can do this with the enclosing scope variables as well and there is a way to do that so let's say within our inner function here that we wanted to actually change the X variable of our outer function now we shouldn't use global because global will affect the global scope in this case we use the non-local statement so up at the top here I'm going to atop of this inner function I'm going to say non-local X and save that now this will allow us to work with the local variables of enclose functions so in this case it means that we're now affecting this X variable of the outer function so now if i uncomment out that inner x and i rerun this and now you can see that it prints out enter X twice and that's because when we set our X here to enter X within our inner function we were actually affecting that local x of our enclosing function so it prints out inner X within this inner function and also when we print it out here it got overwritten here so now it prints out inner X twice now I can actually see the non-local statement being used more often than the global statement because non-local can be useful in order to change the state of closures and decorators and things like that now I'm not going to go into closures and decorators in this video but if you're interested then I do have a video on both of those topics and if you watch those then you could probably think of some use cases where using this non-local statement could be useful ok so now just to wrap all of this up let's remove this non-local statement here and let's uncomment out our global X variable here at the top and here at the bottom I'm going to uncomment out where we print out that global X variable so now if I was to run this we're simply setting an X variable in each of these scopes and then printing them out so now that we've gone over the LD GB rule then you should know exactly what would happen if I was to come in here and comment out where I set the X here within this inner function so if I run that and you can see that when we printed that it didn't find it in its local scope and instead fell back to that enclosing scope and if I was to comment out where I set the X here within this outer function and ran that then you can see that each time we printed all of those X variables then it doesn't find either of these and their local scopes or their enclosing scopes and instead falls back to that global scope in that global X string and if it didn't find anything in that global scope then it would look in that list of built-ins that we looked at earlier and if it doesn't find it there then an error is thrown and also after this video you should know how to use the global and non-local statements to change the values within those scopes if need be so I think that's going to do it for this video if you have any questions about what we covered then feel free to ask in the comment section below and I'll do my best to answer those if you all enjoy these tutorials and would like to support them then there are several ways you can do that the easiest way is to simply like the video and give it a thumbs up and also it's a huge help to share these videos with anyone who you think would find them useful and if you have the means then you can contribute through patreon and there's a link to that page in the description section below be sure to subscribe for future videos and thank you all for watching
Info
Channel: Corey Schafer
Views: 230,781
Rating: 4.9865427 out of 5
Keywords: Python, Scope, Global, Local, Enclosing, Built-ins, LEGB, LEGB Rule, Built-in, Builtin, Variable Scope, Nonlocal, Python Global, Python nonlocal, Python Scope, Python for Beginners, Programming Tutorials, Python Tutorial, Python Tutorials, Software Engineering, How to, How-to, Global Variable, Local Variable
Id: QVdf0LgmICw
Channel Id: undefined
Length: 20min 58sec (1258 seconds)
Published: Tue Dec 20 2016
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.