Learnerslesson
   JAVA   
  SPRING  
  SPRINGBOOT  
 HIBERNATE 
  HADOOP  
   HIVE   
   ALGORITHMS   
   PYTHON   
   GO   
   KOTLIN   
   C#   
   RUBY   
   C++   




PYTHON - SCOPE


'Scope' can be defined as the accessibility of a variable.


Say for example, in every office, there is a restricted area where only a few people have access.


Similarly, in Python, the variables also have some access restrictions. The variables that are defined inside a Function, cannot be accessed outside of it.


Example :


def func():
    x = 5

func()	
print(x)


Output :



  print(x)
 NameError: name 'x' is not defined

Now, the program execution starts from the third line.


java_Collections

And the Function 'func( )' is called.


func( )

And the function execution begins.


def func():
    x = 5

And initialised the variable 'x' with '5' inside the function 'func( )'.


x = 5

java_Collections

Then we come to the print statement,


print(x)

And end up with an error as output,


Output :



  print(x)
 NameError: name 'x' is not defined

This is because the variable 'x' is not accessable outside the Function. And that is called as 'Local Scope'.


Local Scope


The variables that are declared inside a Function, can only be accessed inside the Function and is local to that Function. That is called the 'Local Scope' of a variable.


Say for example, if there are two functions, 'first_func( )' and 'second_func( )'.


Example :


def first_func():
    x = 5
    print("The variable x is not accesible outside the first_func()")
	
def second_func():
    y = 7
    print("The variable y is not accesible outside the second_func()")

first_func()
second_func()	


Output :



  The variable x is not accesible outside the first_func( )
  The variable y is not accesible outside the second_func( )

So, we have declared two functions, 'first_func( )',


def first_func():
    x = 5
    print("The variable x is not accesible outside the first_func()")

And 'second_func( )'.


def second_func():
    y = 7
    print("The variable y is not accesible outside the second_func()")

And we have two variables, 'x' and 'y'.


While 'x' is declared inside the Function 'first_func( )' and is local to the 'first_func( )' and cannot be accessed outside it.


Similarly, 'y' is declared inside the Function 'second_func( )' and is local to the 'second_func( )' and cannot be accessed outside it.


Next, let us see the Local Scope in nested Function.


Local Scope in Nested Function


Nested Function is a Function inside an existing Function.


Example :


def outer_func():
    x = 5
    print("The variable x is accesible from the outer_func() and the value is ", x)
    def inner_func():
        print("The variable x is accesible from the inner_func() and the value is ", x)
    inner_func()	
	
outer_func()


Output :



  The variable x is accesible from the outer_func( ) and the value is 5
  The variable x is accesible from the inner_func( ) and the value is 5

So, in the above example, there are two Functions, 'outer_func( )' and 'inner_func( )'. And the 'inner_func( )' resides inside the 'outer_func( )'.


Now, we have declared a variable 'x' inside the 'outer_func( )'.


def outer_func():
    x = 5
    print("The variable x is accesible from the outer_func() and the value is ", x)
    def inner_func():
        print("The variable x is accesible from the inner_func() and the value is ", x)
    inner_func()

Now, since the 'inner_func( )' resides inside the 'outer_func( )'. The variable 'x' is also accessable inside the 'inner_func( )'.


Now, what if, the variable 'x' was defined inside the 'inner_func( )'. Can the variable 'x' be accessed from the 'outer_func( )'?


Well! The answer is no.


Let us see the above example.


Example :


def outer_func():
    print("The variable x is not accesible from the outer_func()")
    def inner_func():
        x = 5
        print("The variable x is accesible from the inner_func() and the value is ", x)
    inner_func()	
	
outer_func()


Output :



  The variable x is not accesible from the outer_func( )
  The variable x is accesible from the inner_func( ) and the value is 5

So, in the above code, we have declared the variable 'x' inside the 'inner_func( )'.


def outer_func():
    print("The variable x is not accesible from the outer_func()")
    def inner_func():
        x = 5
        print("The variable x is accesible from the inner_func() and the value is ", x)
    inner_func()

So, the variable 'x' is not accesible from the 'outer_func( )'.


So, the moral of the story is, the variable that is declared at a higher scope could be accessed at a lower scope.


Say for example, your Boss will have access to your details. But you will not have access to any of your Boss's details.


And with this we come to the concept of 'Global Scope'.


Global Scope


The variables that are declared outside the Function are accessable inside a Function. And they are said to be in 'Global Scope'.


Let us see in the below example :


Example :


x = 5
def func():
    print("Inside the function ",x)
    
func()	
print("Outside the function ",x)


Output :



  Inside the function 5
  Outside the function 5

So, in the above example, we have declared a variable 'x', outside the Function and initialised with '5'.


x = 5

java_Collections

Now since, the variable 'x' is declared outside the Function, it is accessible both inside and outside the Function.


Now, we were able to access the variable 'x' inside the Function. But what if, we wanted to change/modify the value of 'x'.


Example :


x = 5
def func():
    x = 8
    print("Inside the function ",x)
    
func()	
print("Outside the function ",x)


Output :



  Inside the function 8
  Outside the function 5

In the above code, we get a strange output. Let us see how?


The program execution starts by initialising the global variable 'x' with the value '5'.


java_Collections

x = 5

java_Collections

Then we come to the next line where Function 'func( )' is called


func( )

java_Collections

And the Function 'func( )' execution begins,


def func():
    x = 8
    print("Inside the function ",x)

In the first line of the Function 'func( )'. The value of 'x' is initialised with '8'.


x = 8

java_Collections

Now, this is time to pause and note something very IMPORTANT. i.e. If a variable is declared inside a Function. Then it is treated as a different variable.


In this case, since the value of 'x' is initialised with '8'. It is treated as a redefinition.


And 'x' is a new variable altogether.


That is the reason why, the print statement inside the Function 'func( )',


print("Inside the function ",x)

Prints the value '8'. i.e. The value of the above variable in the local scope.


Inside the function 8

Then the control comes out of the Function 'func( )' and the next print statement,


print("Outside the function ",x)

java_Collections

Prints the value of the global variable i.e. '5'.


Outside the function 5

So, the moral of the story is, there are two different variables with the same name 'x'.


  1. 'x = 5' is the variable declared for Global Scope.
  2. 'x = 8' is the variable in local scope.

Let us look at another example,


Example :


x = 5
def func():
    x = x + 6
    print("Inside the function ",x)
    
func()	
print("Outside the function ",x)


Output :



  x = x + 6
 UnboundLocalError: local variable 'x' referenced before assignment

And we end up with the below error.


Any guesses why?


Let's investigate.


The error occurred with the statement,


x = x + 6

Which is inside the Function 'func( )'.


Now since, there is this assignment operator (i.e. '=') in 'x = x + 6', the variable 'x' is treated as a new variable declaration.


Although, the variable 'x' is defined with the initial value '5'.


x = 5

But that is declared in 'Global Scope'.


So, we end up with the error,


UnboundLocalError: local variable 'x' referenced before assignment

Now, to resolve the above problem, 'global' keyword comes for rescue.


Global Keyword


So, in the above example we have seen that if we wanted to make any changes to a variable inside the Function. It would be treated as a Local Variable for that Function.


With the help of 'global' keyword, we can get rid of that.


Let us see in the below example.


Example :


x = 5
def func():
    global x
    x = x + 6
    print("Inside the function ",x)
    
func()	
print("Outside the function ",x)


Output :



  Inside the function 11
  Outside the function 11

And we got rid of the error with the 'global' keyword.


All we have done is, inside the Function 'func( )',


def func():
    global x
    x = x + 6
    print("Inside the function ",x)

We have declared the variable 'x' with the keyword 'global'.


global x

And 'x' is the global variable now. In other words, we have converted the local variable to a global variable using the 'global' keyword.


Next, let us see, how the 'global' keyword can be used in nested Functions?


Global variables in Nested Functions


Example :


def outer_func():
    x = 5
    
    def inner_func():
        global x
        x = 9
        
    print("Before calling inner_func the value of x is ", x)
    inner_func()
    print("After calling inner_func the value of x is ", x)
    
outer_func()
print("Value of x outside the function ", x)


Output :



  Before calling inner_func the value of x is 5
  After calling inner_func the value of x is 5
  Value of x outside the function 9

So, in the above code, we have declared two functions :


  1. def outer_func( ):
  2. def inner_func( ):

The 'inner_func( )' is inside the 'outer_func( )'.


Now, in the 'outer_func( )', we have declared a local variable 'x'


x = 5

Inside the 'outer_func( )'.


def outer_func():
    x = 5
    def inner_func():
        global x
        x = 9

Now, to access the same local variable 'x' inside the 'inner_func( )',


def inner_func():
    global x
    x = 9

We tried the 'global' keyword before 'x'.


global x

And initialised it with '9'.


x = 9

But the problem with this approach is, this 'x' with 'x = 9' becomes a global variable. i.e. This 'x' is not the same local variable 'x' in 'outer_func( )'.


So, 'x = 9' becomes a global variable and 'x = 5' is a local variable that is local to 'outer_func( )'.


And we end up with two variables again.


To overcome this problem, there is another keyword called 'nonlocal'.


Nonlocal Keyword


Let us rewrite the above example with 'nonlocal' keywotd.


Example :


def outer_func():
    x = 5
    
    def inner_func():
        nonlocal x
        x = 9
        
    print("Before calling inner_func the value of x is ", x)
    inner_func()
    print("After calling inner_func the value of x is ", x)
    
outer_func()


Output :



  Before calling inner_func the value of x is 5
  After calling inner_func the value of x is 9

Now, the above problem is solved after using the 'nonlocal' keyword,


nonlocal x

So, the local variable 'x' inside the 'outer_func( )',


x = 5

Is same as the local variable 'x' inside the 'inner_func( )'.


x = 9