Python Scope & the LEGB Rule


Name and Scopes in Python

As we know that python is a dynamically-typed language. Variables come into existence when we first time assign a value, similarly functions and classes are available after we define them by using keywords def and class, modules exists in the code after we import them. All these things can be accessed by the name we assign, and each name has its scope.

In Python, scope rule says that how and where variables and names are lookup.

It determines the visibility of a variable within the python code. The scope of variable or name depends upon where we create the variable. Python has the following scopes where it look up for the variables and names

  1. Local
  2. Enclosing
  3. Global and
  4. Built-in

This is also known as LEGB rule. It determines both, the level and the sequence to resolve the names in python code.

Local(or function) Scope

A variable or name created inside a function has local scope, and can only be used inside that function.

def myFunc():
    a = 100  local variable
    print(a)

myFunc()

[OUTPUT]
100

Now, if we try to access this variable a, outside of this function , we will get error because it has local scope.

def myFunc():
    a = 100
    print(a)

print(a) # accessing outside of function
OUTPUT
Traceback (most recent call last):
  File "C:/Users/hp/PycharmProjects/untitled/script.py", line 5, in 
    print(a)
NameError: name 'a' is not defined

Function inside a Function (Nested / Inner Function )

As we can see in the above example, a is not accessible outside of the function, but it can be accessed within the nested function.

def myFunc():
    a = 100
    def innerFunc():
        print(a) # accessing within inner function
    innerFunc()

myFunc()

[OUTPUT]
100

Enclosing(or nonlocal) scope

Enclosing scope exists only for nested / inner functions. As we have seen in the just above example, the local variable of outer function is accessible from the nested function. Nested function is defined in the enclosing scope of outer function thats's why this is possible, the outer function's variables will be nonlocal for nested function because nested function has its own local scope.

Updating nonlocal variable

def myFunc():
    a = 100 # local variable
    def innerFunc():
        a = 150 # try to change the value of a
        print("inside nested function a = ",a)
    innerFunc()
    print("outside of nested function a = ",a)
myFunc() 
OUTPUT
inside nested function a =  150
outside of nested function a =  100 

As we can see in the above example, we are trying to update the value of outer function's a, inside the nested function. When we call the function innerFunc(), we are getting the output as a = 150, but after calling the innerFunc(), when we are accessing the value of outer function's a's value, we are getting the output as a = 100. It shows that the nonlocal variable is not updated. Actually what happens, when we assign a value to any variable , python creates a new variable. In the above program, the same thing happens, instead of updating the value of nonlocal variable a, it creates a new one which has local scope to nested function.

nonlocal keyword

For the above scenario, if we want to update the nonlocal variable within the nested function then first we have to tell the nested function that don't create a local variable with the given name, point to the variable of outside enclosing function. To do this we use keywordnonlocal.

def myFunc():
    a = 100
    def innerFunc():
        nonlocal a # mention only name with nonlocal keyword
                          # this will pint to variable of outer function
        a = 150 # now updation will take place
        print("inside nested function a = ",a)
    innerFunc()
    print("outside of nested function a = ",a)
myFunc()
OUTPUT
inside nested function a =  150
outside of nested function a =  150 

Now, see the output, value of a is updated.


Global(or module) scope

A variables or names created outside of any function or we can say defined in python module direct, have global scope. Global variables are available from within any scope, global and local.

a = 100 # # global variable
def myFunc():
    print("inside function a = ",a) # available in function also

myFunc()

print("outside of function a = ",a)
OUTPUT
inside function a =  100
outside of function a =  100

We can see that variable a, is also available in function.

Global Keyword

The global keyword can be used in two ways:

1. if we want to make a change to a global variable inside a function.

a = 100
def myFunc():
    global a # only write name
    a = 20
    print("inside function a = ",a)

myFunc()

print("outside of function a = ",a)
OUTPUT
inside function a =  20
outside of function a =  20 # both are same

2. If we need to create a global variable, in the local scope.

The global keyword makes the variable global.

def myFunc():
    global a # creating a global variable
    a = 20
    print("inside function a = ",a)

myFunc()

print("outside of function a = ",a) # also available here
OUTPUT
inside function a =  20
outside of function a =  20 # both are same

Built-in scope

Python built-in scope is a scope which is implemented as a standard library module named builtins in Python 3. So, whatever is defined in it, those are by default available in every python script and can be accessed from anywhere. We can check that what are things available from this scope....

print(dir(__builtins__))
                
OUTPUT
['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException', 
'BlockingIOError', 'BrokenPipeError', 'BufferError', 'BytesWarning', 
'ChildProcessError', 'ConnectionAbortedError', 'ConnectionError', 
'ConnectionRefusedError', 'ConnectionResetError', 'DeprecationWarning', 
'EOFError', 'Ellipsis', 'EnvironmentError', 'Exception', 'False', 
'FileExistsError', 'FileNotFoundError', 'FloatingPointError', 
'FutureWarning', 'GeneratorExit', 'IOError', 'ImportError', 
'ImportWarning', 'IndentationError', 'IndexError', 'InterruptedError',
 'IsADirectoryError', 'KeyError', 'KeyboardInterrupt', 'LookupError', 
'MemoryError', 'ModuleNotFoundError', 'NameError', 'None', 'NotADirectoryError',
 'NotImplemented', 'NotImplementedError', 'OSError', 'OverflowError', 
'PendingDeprecationWarning', 'PermissionError', 'ProcessLookupError', 
'RecursionError', 'ReferenceError', 'ResourceWarning', 'RuntimeError', 
'RuntimeWarning', 'StopAsyncIteration', 'StopIteration', 'SyntaxError', 
'SyntaxWarning', 'SystemError', 'SystemExit', 'TabError', 'TimeoutError', 'True',
 'TypeError', 'UnboundLocalError', 'UnicodeDecodeError', 'UnicodeEncodeError', 
'UnicodeError', 'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning', 
'ValueError', 'Warning', 'WindowsError', 'ZeroDivisionError', 
'__build_class__', '__debug__', '__doc__', '__import__', '__loader__', 
'__name__', '__package__', '__spec__', 'abs', 'all', 'any', 'ascii', 'bin', 
'bool', 'breakpoint', 'bytearray', 'bytes', 'callable', 'chr', 'classmethod', 
'compile', 'complex', 'copyright', 'credits', 'delattr', 'dict', 'dir', 'divmod', 
'enumerate', 'eval', 'exec', 'exit', 'filter', 'float', 'format', 'frozenset', 
'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex', 'id', 'input', 'int', 
'isinstance', 'issubclass', 'iter', 'len', 'license', 'list', 'locals', 'map', 
'max', 'memoryview', 'min', 'next', 'object', 'oct', 'open', 'ord', 'pow', 
'print', 'property', 'quit', 'range', 'repr', 'reversed', 'round', 'set', 
'setattr', 'slice', 'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', 
'type', 'vars', 'zip'] 

As we can see, list is very long. All the above classes, functions, keywords ect.. are by default available in python script. This list may vary from version to version.


Name Resolution

If we are accessing any variable or name in our code, python first look which part is trying to access. Accordingly start searching for tht name and follows the LEGB rule. First look into Local scope, if not found then look into Enclosing scope, if again not found then look for Global scope, if the name is not found then go for Built-in scope , if the name is also not there, then it raise exception.

G = 10
E = 50
L = 100
def myFunc():
    E = 20
    L = 150
    def innerFunc():
        L = 30
        print("L = ",L)
        print("E = ", E)
        print("G = ",G)
        print("Built-in",sum([1,2,3]))
    innerFunc()

myFunc()
OUTPUT
L =  30
E =  20
G =  10
Built-in 6

Next chapter is Anonymous Function





Video Lecture



 




Training For College Campus

We offers college campus training for all streams like CS, IT, ECE, Mechanical, Civil etc. on different technologies like
C, C++, Data Structure, Core Java, Advance Java, Struts Framework, Hibernate, Python, Android, Big-Data, Ebedded & Robotics etc.

Please mail your requirement at info@prowessapps.in


Projects For Students

Students can contact us for their projects on different technologies Core Java, Advance Java, Android etc.

Students can mail requirement at info@prowessapps.in


CONTACT DETAILS

info@prowessapps.in
(8AM to 10PM):

+91-8527238801 , +91-9451396824

© 2017, prowessapps.in, All rights reserved