globals() and locals() Method in Python


The built-in functions globals() and locals() returns the global and local symbols table respectively. Python interpreter maintains a data structure containing information about each identifier appearing in the program's source code. This information is about the type, value, scope level, and location of an identifier (also called symbol).

Compiler/interpreter uses these symbol tables for various purposes such as:

  1. store tall entities so that they can be retrieved efficiently.
  2. verify if an object has been declared.
  3. determine the scope of an object.
  4. type checking and semantic accuracy.

Python interpreter uses the dictionary object to hold this information. As mentioned above, the symbols may be variables, functions, and classes etc. Such collection of symbols available to the interpreter at the module level (Python's interactive console is also treated to be at module level) is stored in a dictionary returned by the globals() function.

Consider the following example:

Example: globals()
>>> num1=100
>>> num2=200
>>> name="TutorialsTeacher"
>>> def add(x,y):
        z=x+y
        return z
    
>>> globals()
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, 
'__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, 'num1': 100, 'num2': 200, 
'add': <function add at 0x000001E63FBE1AF8>, 'name': 'TutorialsTeacher'}

At module level and inside interactive shell environment, the locals() function also returns the same dictionary.

Example: locals()
>>> locals()
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, 
'__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, 'num1': 100, 'num2': 200, 
'add': <function add at 0x000001E63FBE1AF8>, 'name': 'TutorialsTeacher'}

Let's check what these functions return from within a function by modifying the add() function as follows:

Example: globals() nand locals()
>>> def add(x,y):
        z=x+y
        print ('global symbol table:', globals())
        print ('local symbol table:', locals())
        return z

>>> add(num1, num2)   
global symbol table: {'__name__': '__main__', '__doc__': None, '__package__': None, 
'__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, 
'__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, 
'num1': 100, 'num2': 200, 'add': <function add at 0x000001E63FBD15E8>, 'name': 'TutorialsTeacher'}
local symbol table: {'x': 100, 'y': 200, 'z': 300}

As you can see, the global symbol table remains the same. However, when the add() function is called by passing num1 and num2, their values are assigned to formal argument variables x and y, which are local to the add() function. Hence the local table is updated with x, y and z.

Note that if a variable that is already present in global scope is declared in a local scope of a function as well, the compiler gives priority in the local scope. Further, change of its value inside function doesn't affect it in the global space.

Example: Changes in Global Scope
x=10
def myfunction():
    x=10
    x=x*2
    print ('x inside function: ', x)
myfunction()
print ('x in global scope: ',x)
Output
x inside function: 20
x in global scope: 10

We can modifying the global variables using the globals() dictionary, as shown below.

Example: Modify Global Dictionary
x=10
def myfunction():
    x=globals()['x']
    x=x*2
    globals()['x']=x                  
    print ('global variable x inside function: ',x)
    return
myfunction()
print ('global variable x in global scope: ',x)
Output
global variable x inside function:  20
global variable x in global scope:  20

Python also has a global keyword. It allows a globally declared variable to be used and modified inside a function, ensuring that the modifications are reflected globally as well.

Example: global keyword
x=10
def myfunction():
    global x
    x=x*2                  
    print ('global variable x inside function: ',x)
    return
myfunction()
print ('global variable x in global scope: ',x)
Output
global variable x inside function: 20
global variable x in global scope: 20

In a situation of nested functions, variables present in the outer function's namespace can be used in the inner function by declaring global.

Example: Scope in Inner Function
def outer(): 
     x1 = 15
     print ('in outer function:',x1)  
     def inner(): 
            global x1
            x1 = 30
            print ('value inside function',x1)
            
            
     inner() 
     print("After inner function: ", x1) 
  
outer() 
print("value of x1",x1) 
Output
in outer function: 15
value inside function 30
After inner function:  15
value of x1 30

Python also has the nolocal keyword that allows a variable declared in global (outer space).

Example: nolocal keyword
def outer(isnolocal):
    x2=100
    print ('value in outer function:',x2)
    
    def withnolocal():
        nonlocal x2
        x2=50
    
    def withoutnolocal():
        x2=50
    
    if isnolocal==True:
        withnolocal()
    else:
        withoutnolocal()
    
    return x2
        
print (outer(True))
print (outer(False))
Output
value in outer function: 100
50
value in outer function: 100
100

Above, the outer() function has two nested functions. Both try to modify a variable declared in the outer function. We can see that the inner function withnolocal having nolocal x2 declaration can modify the outer variable x2, but changes inside the withoutnolocal() without nolocal are not reflected.