To understand what is happening in the code, you should know what the “scope” of variable means. The scope of a variable refers to the places from where we can see or access a variable. To understand this more clearly, we should first know what “variable” actually means.
A variable is a reference to a memory address that contains the value. Let’s see the figure below.
Suppose, we have x=5. There are two ways of reading this line.
- ‘x’ is a variable name that references to a memory location in which 5 is stored.
- variable x equals 5
Saying the humungous first line every time may be frustrating, so we usually use the second way. Here comes the confusion. Let’s see by an example
1 2 3 4 5 6 7 8 |
x = 5 def number(): x = 3 def numb(): x = 6 number() numb() print x |
Question: How many variables are there in the above code?
If we use the definition x equals 5, we might think that it is the same variable x with different values. But if we use the actual definition of the variable, we can argue that there are 3 variables as they refer to different memory locations and thus are different. We can always check the identity of the location of the object in memory using the python id() function. Just write id(variable_name) which outputs a number that refers to some memory location(same number means the same variable). So, use the shortcut definition but always remember the actual meaning.
This means we can define a number of variables with the same name(say x) in a program without having a relation between them. This sometimes creates confusion. Let’s understand this by an example
1 2 3 4 5 |
x = 5 def number(): x = 3 number() print x |
Now, which value should this x prints? This is where the scope comes into the picture. Scope tells us which variable we can access and from where.
LEGB Rule: LEGB stands for Local, Enclosing, Global and Built-in. This tells us the order in which python accesses the variable in a program. First, python will check if the variable is present in the local scope, if not then checks in enclosing scope and so on till the builtin scope is checked.
Let’s understand the LEGB terms one by one:
- Local: Python first tries to search for an identifier(variable) in Local scope. The local variable exists only within the block/function that it is declared in. When that block/function ends, the local variable has no significance, it gets destroyed. We cannot use it outside the function where it is declared. For example in the code below, x=3 is local to the number() function means we cannot access that variable outside this function. So, the output of the last print(x) will be an error saying name ‘x’ is not defined.
12345def number():x=3print xnumber() # 3print x # name 'x' is not defined - Enclosing: Enclosing refers to the nested functions where one encloses the other. If Python does not find an identifier(variable) within the local scope, it will examine the Enclosing scope to see if it can find the variable there. Let’s understand this by an example
12345678def outer():x=4def inner():print x #----- 1inner()print x #----- 2outer()
For the print x —1, inner() is Local and outer is Enclosing while for the print x—2, outer() is Local. So, print x—1 will first search for x in the inner(). Since there is no x in the inner() so we go to outer()/Enclosing and check if x is there or not. So, print x—1 outputs 4. For print x–2, we have x in the Local scope of outer() so this will output 4. - Global: Global variable means that it is accessible from anywhere in your script, including from within a function. It is usually defined at the top of the script or outside of the function. If Python fails to find the variable in both above scopes, then it will check the global scope. Let’s see an example
12345678x=4def outer():def inner():print x #----- 1inner()print x #----- 2outer()
As we have no x in the local and enclosing scope, so Python checks the global scope and outputs 4 for both print x statements.
Note: using too many global variables will generally lead to name conflicts and will likely lead to unwanted side effects. - Built-in: Built-in means the function and variables that are already defined in python. If an identifier is not found in any of the above scopes within a module, then Python will examine the built-in identifiers to see if it is defined there. For example
12x = len ( 'PANKAJ' )print x # 6
If len is not found in any of the scopes, then Python would consult the Built-In scope, where it will find the len function and outputs 6. But if we create our own len function then it will have precedence over Built-in len function. Let’s see by an example
1234def len(x):return (1)x = len ( 'PANKAJ' )print x # 1
Since our len function precedes over built-in len and thus the output of print x statement equals 1.
Now, I hope that you might have understood the Python variable and scope, Let’s look at some of the keywords that are useful regarding this
- Global Keyword: With this, we tell the Python to use the globally defined variable instead of locally defining it. This is useful when we want to change the value of a variable through a function. To use it, simply type global followed by the variable name. Let’s see an example
1234567x=4def change(y):global xx = ychange(10)print (x) # 10 - NonLocal Keyword: This is useful in nested functions. It causes the variable to refer to the previously bound variable in the closest enclosing scope. Let’s see by an example
12345678910def outer():x=4def inner():nonlocal xx = 10print (x)inner()print (x)outer() # output 10,10
By nonlocal, we tell Python that this x is same as defined in the enclosing outer() function.
Now, you might have got some feeling about the Python variable and scope. Hope you enjoy reading.
If you have any doubt/suggestion please feel free to ask and I will do my best to help or improve myself. Good-bye until next time.