Skip to main content

Python Namespace and Scope

What is an Identifier in Python?

An identifier is a name given to objects and is used to access the object to which it refers.

note

Remember that everything in Python is an object!.

For example:

a = 2
print(id(a)) # 9789024

a = a + 1
print(id(a)) # 9789056

print(id(3)) # 9789056

b = 2
print(id(b)) # 9789024
print(id(2)) # 9789024
note

You can get different values for the id but, in any case, the variables pointing to object 2 will have the same id() because they point to the same object!

In the picture is shown the memory diagram of the variables involved in the previous example: Memory diagram of variables of the example

Explanation:

  1. Initially an object 2 is created with the name a associated with it;
  2. When a = a+1 is executed, a new object 3 is created and a is associated with this object. Now id(a) and id(3) have the same values.
  3. When b = 2 is created, the new name b is associated with the previous object 2.
note

An identifier can refer to any type of object.

a = 123
a = 'A String'
a = [1,2,3]

The same applies to functions, since functions are also objects.

def sayHello():
print("Hello")

a = sayHello

a()

What is a Namespace in Python?

A namespace is a collection of names.

It is a system that provides a unique name for each object (such as variables and methods). A namespace is saved in the form of a Python dictionary.

note

Different namespaces may coexist at any given time, but they are completely isolated.

Types of namespaces

In a Python, there are three types of namespaces:

  1. Built-In namespace: it is created when we start the Python interpreter and exists as long as the interpreter runs.
  2. Global namespace: each module creates its own global namespace
  3. Local namespace: it is created when a function is called, which has all the names defined in it

Diagram of different namespaces in Python

Python Variable Scope

A scope is the portion of a program from where a namespace can be accessed directly without any prefix.

note

You may not be able to access every namespace from every part of the program.

At any given moment, there are at least three nested scopes:

  1. Scope of the current function that has local names.
  2. Scope of the module that has global names.
  3. Outermost scope that has built-in names.

For example:

# var1 is in the global namespace
var1 = 1
def a_function():

# var2 is in the local namespace
var2 = 2
def an_inner_function():

# var3 is in the nested local namespace
var3 = 3
note

When a reference is made inside a function, the name is searched in the local namespace, then in the global namespace and finally in the built-in namespace.

If there is a function inside another function, a new scope is nested inside the local scope.

Examples

Scope Example

Thanks to isolation between namespaces, there may be multiple objects with the same name present in different namespaces.

Consider the following example:

a = 10

def outer_function():
b = 20
def inner_func():
c = 30

The following observations can be made:

  • The variable a is in the global namespace.
  • The variable b is in the local namespace of outer_function().
  • The variable c is in the nested local namespace of inner_function().
  • When you are in inner_function(), c is local to you, b is nonlocal and a is global. You can read and assign new values to c and you can only read a and b from inner_function()
  • Trying to assign a value to variable b involves the creation of a new variable b that is different that nonlocal b variable. The same thing happens when you try to assign a value to variable a

Global Example

If a is declared as a global variable, all references and assignments are made to the global variable a.

Consider this example:

Without Global
def outer_function():
a = 2

def inner_function():
a = 3
print('inner a =', a)

inner_function()
print('outer a =', a)


a = 1
outer_function()
print('global a =', a)

Output

inner a = 3
outer a = 2
global a = 1
With Global
def outer_function():
global a
a = 2

def inner_function():
global a
a = 3
print('inner a =', a)

inner_function()
print('outer a =', a)


a = 1
outer_function()
print('global a =', a)

Output

inner a = 3
outer a = 3
global a = 3
note

Note that in the second example, all references and assignments are to the global a, thanks to the use of the global keyword.