Python Namespace and Scope

FREE Online Courses: Click, Learn, Succeed, Start Now!

You would have come across ‘Name’ that we use to refer to an object/ person. You would have also come across ‘Space’ in science and mathematics. Are you wondering what this “Namespace” is?

If yes, then let’s not wait and begin.

Introduction to Namespace in Python

Before discussing this, let us remember what does ‘Name’ means in Python?

In Python, everything is an object like variable, function, etc. A name is nothing but something that we use to refer to an object. It is also called an identifier.

For example, in the code below, ‘text’ is an identifier to the variable that stores ‘PythonGeeks’.

Example of name in Python:

text="PythonGeeks"

To check if the ‘text’ variable stores “PythonGeeks” , we can see the address in which they are stored in the memory. We can use the built-in function ‘id()’ for this purpose.

Example of using id() function:

text="PythonGeeks"
print("id of text is:",id(text))

print("id of PythonGeeks is:",id("PythonGeeks"))

Output:

id of text is: 2200767484144

id of PythonGeeks is: 2200767484144

We can see that the memory addresses of ‘text’ and “PythonGeeks” are the same. Let us see another example where the variable value changes.

Example of memory allocation while variable changes:

name="Python"
print("id of name:",id(name))

print("id of Python:",id("Python"))

name ="PythonGeeks"
print("id of name:",id(name))

print("id of PythonGeeks:",id("PythonGeeks"))

text="Python"
print("id of text:",id(text))

print("id of Python:",id("Python"))

Output:

id of name: 2786126438960

id of Python: 2786126438960

id of name: 2786161874800

id of PythonGeeks: 2786161874800

id of text: 2786126438960

id of Python: 2786126438960

The following actions happened in the above code:

memory allocation in Python

A Namespace is a collection of names along with the information of the object it refers to. It maps names to the objects.

  • More than one namespace can exist at an instant, but they all work isolated.
  • Due to this isolation, two namespaces can have the same name and these will be independent of each other.
  • It can be thought of as a dictionary, where name-object pairs exist.
  • The lifecycle of a namespace is the time for which the object in the scope is accessible. When the scope of the object ends, the object gets deleted. Thus different objects have different time duration for which it exists in the memory, which decides the life cycle.
  • The life cycle reduces from built-in namespace to global namespace to inner namespaces.

Example of lifecycle of a Namespace:

var1 = "Python" #var 1 is in global namespace
def outer():
  var2=10.4 #var2 is in local namespace
  def inner():
    var3=3 #var3 is in nested local namespace

In the above example, the variable ‘var1’ is outside the functions. So, it is in the global namespace. Whereas ‘var2’ is inside the ‘outer()’ sunction, so its name space is local. Coming to the ‘var3’, it is inside the nested function ‘inner()’. So, it is in a nested local namespace.

Types of Namespace in Python

Based on the part of the code the objects belong to, namespaces are of the following types:

Types of Namespace in Python

a. Built-in Namespace in Python

This namespace gets created when the interpreter starts. It stores all the keywords or the built-in names. This is the superset of all the Namespaces. This is the reason we can use print, True, etc. from any part of the code.

b. Python Global Namespace

This is the namespace that holds all the global objects. This namespace gets created when the program starts running and exists till the end of the execution.

Example of Global Namespace in Python:

text="PythonGeeks"
def func():
    print(text)

func()
print(text)

Output:

PythonGeeks
PythonGeeks

We can see that we can access the variable ‘text’ from any part of the program. This is a global variable and exists in the global namespace.

c. Python Local Namespace

This is the namespace that generally exists for some part of the time during the execution of the program. This stores the names of those objects in a function. These namespaces exist as long as the functions exist. This is the reason we cannot globally access a variable, created inside a function.

Example of local namespace:

var1="PythonGeeks"
def func():
    var2="Python"
    print(var2)

  
func()

Output:

Python

Here the local namespace is created when the ‘func()’ is called and stores ‘var2’. This namespace gets deleted when the use of ‘func()’ is done. Because of this when we try to access ‘var2’ outside, globally, we get an error as shown below-

Example that shows we cannot access local variable globally:
print(var2)

Output:

Traceback (most recent call last):
File “<pyshell#7>”, line 1, in <module>
print(var2)
NameError: name ‘var2’ is not defined

Also, it is important to observe that whenever a global variable is a modifier in a function, the change doesn’t get reflected at the global level. For further discussion look at the following code:

Example of using same name for global and local variable:

var= "PythonGeeks"
def func():
    var="Python"
    print(var)

  
func()
print(var)

Output:

Python
PythonGeeks

When we print ‘var’ inside the function we could see the changed value but couldn’t observe the same outside the function. This is because the local namespace is isolated and creates its own variable ‘var’.

To avoid this we can use the keyword ‘global’ inside the function for the ‘var’.
Look at the below results.

Example on use of ‘global’ keyword:

var="PythonGeeks"
def func():
    global var
    var="Python"
    print(var)

  
func()
print(var)

Output:

Python
Python

The use of global keywords tells the interpreter to use the global variable, rather than creating its own. This makes us observe the changes globally.

The same concept applies to nested functions, a local namespace exists separately for that function. And it exists only during the function’s execution.

Example showing variable in inner function is out of scope for outer one:

def outer():
  def inner():
    var="PythonGeeks"
    print(var)
  inner()
  print(var)

  
outer()

Output:

PythonGeeks
Traceback (most recent call last):
File “<pyshell#9>”, line 1, in <module>
outer()
File “<pyshell#8>”, line 6, in outer
print(var)
NameError: name ‘var’ is not defined

We can see that we could access the ‘var’ inside ‘inner()’ but not in the outer function. This is because of the deletion of the namespace after the use of the inner function.

Similar to the global case, when we have a nested function, the changes done in the inner function do not get reflected in the outer function. For this, we use the ‘nonlocal’ keyword as shown below.

Example of using same name for variables in inner and outer functions:

def outer():
  var="PythonGeeks"
  def inner():
    nonlocal var
    var="Python"
    print(var)
  inner()
  print(var)

  
outer()

Output:

Python
Python

Scope in Python

The scope of an object or a variable is the part of the code where this object/variable can be accessed. All the variables are not available throughout the program. Some variables get created and deleted in between the runtime.

For example, a variable in a function gets created only when the function is called and exists only during the execution of the function. If we try to access it globally, we fail and get an error.

Example on Scope of a variable:

def func():
  var="PythonGeeks"
  print("Inside the function, value of var:",var)

  
func()

print("Outside the function, value of var:")
print(var)

Output:

Inside the function, value of var: PythonGeeks
Outside the function, value of var:
Traceback (most recent call last):
File “<pyshell#6>”, line 1, in <module>
print(var)
NameError: name ‘var’ is not defined

We can see that the variable ‘var’ couldn’t be accessed outside the function.

Because of different isolated namespaces created, we have different scopes and these are of four types:

a. Built-in scope: This is the scope of all the keywords. This is the largest scope. These load when the interpreter starts and we can access them from any part.

b. Global scope: This is the scope of the variables that are created outside the functions. These can be accessed from any part of the program.

c. Local scope: This is the scope of the variables created inside the functions. These exist only while the function is executing. We cannot access them outside the function.

d. Enclosed or nonlocal scope: This case occurs when we have nested functions. The variables in the outer function are neither global nor local to the inner function. These have nonlocal scope.

Scope in python

We have at least three Python scope, that is, built-in, global and local. Accordingly, we have the corresponding namespaces. The enclosed scoped variables come under nested local namespace.

These decide which reference of the variable is given preference while accessing its value. This is called the “LEGB” rule. According to this, the preference order is Local-> Enclosed-> Global -> Built-in.

Let us revise all the above concepts by discussing the below example:

Example on namespace and scope:

name ="a"
def fun1():
  name ="Python"
  def fun2():
    global name
    name ="Geeks"
    def fun3():
      global name
      name="PythonGeeks"
      print("Inside fun3(), value of name:",name)
    print("Before calling fun3(), value of name in fun2():",name)
    fun3()
    print("After calling fun3(), value of name in fun2():",name)
  print("Before calling fun2(), value of name in fun1():",name)
  fun2()
  print("After calling fun2(), value of name in fun1():",name)

print("Before calling the functions, value of name outside the functions:",name)

fun1()

print("After calling the functions, value of name outside the functions:",name)

Output:

Before calling the functions, value of name outside the functions: a
Before calling fun2(), value of name in fun1(): Python
Before calling fun3(), value of name in fun2(): Geeks
Inside fun3(), value of name: PythonGeeks
After calling fun3(), value of name in fun2(): PythonGeeks
After calling fun2(), value of name in fun1(): Python
After calling the functions, value of name outside the functions: PythonGeeks

Initially, the global variable ‘var’ has ‘a’ as the value. So, in the first print statement, the result is ‘a’. Inside the ‘fun1()’, when ‘var’ is given a new value, it creates a new variable in its local namespace. So, this value neither affects the global ‘var’ nor gets affected by the changes on global ‘var’.

Example on namespace and scope in Python

But inside the other two nested functions, ‘fun2()’ and ‘fun3()’, we are using the ‘global’ keyword. These do not create any local variables, rather it modifies the global ‘var’.

So, before and after calling next functions, the value of ‘var’ in ‘fun1()’ did not change. On calling ‘fun2()’, global ‘var’ changed to “Geeks”. And printed “Geeks” on accessing. But on calling ‘fun3()’, the global ‘var’ changed to “PythonGeeks”. And this value is printed, in all ‘fun3’, ‘fun2’ and globally.

Python Interview Questions on Namespace and Scope

Done with learning the concepts. Let us have a look at some of the interview questions under this topic.

Q1. Write a code with inner function and find namespaces are involved in the code? And write them in the increasing order of their lifecycle.

Ans 1. Example of different namespaces:

var="Python"
def func1():
  var="PythonGeeks"
  def func2():
    global var
    var="python"
  func2()
func1()

Two namespaces are involved in the code, global and local. The life cycle of global ‘var’ holdin “Python” and later changed to ‘python’ has a bigger life cycle than the ‘var’ in func1().

Q2. On running the below code, name the variables and values that have the same memory address. Show this using the built-in function.

num1=9
num1=num1+0
num2=9
num3=4
num3=num2*num3

Ans 2. After running this code block, (num1,num2,9) get stored in the same address. The variable num3 uses a different memory address and 4 another address. This is shown in below code

Example on finding the memory allocation of variable:

id(num1)
id(num2)
id(9)

id(4)

id(num3)

Output:

2786124130864
2786124130864
278612413086427861241307042786124131728

Q3. Show the effect of the ‘global’ keyword inside a function using a coding example.

Ans 3. We can use the ‘global’ keyword to make the local changes on a global variable effective even at global level. Below code represents this.

Example of using ‘global’ keyword:

text="Geeks"
def fun():
    global text
    text="PythonGeeks"
    print("Inside the function text is ",text)
    fun()

print(text)

Output:

Inside the function var is PythonGeeks

PythonGeeks

Q4. We know that the global and local variables can have the same name. Can these variables be given the same name as variables in the built-in namespace? Show the result using a coding example.

Ans 4. No, the variables in the built-in scope are the keywords loading when the interpreter starts. Since keywords cannot be identifiers, we cannot use these as global or local variables. For example, we can see that the below code gives an error because of using ‘None’ as a variable name.

var=5
def func():
    None = 0

Output:

SyntaxError: cannot assign to None

Q5. Show the effect on the local variable due to use of global keyword in the nested function. If all the variable names are the same.

Ans 5. There will be no effect on the local variable. The effect will be only inside the inner function and globally, as they use the same global namespace. The local namespace, which is isolated, does not change.

name ="PythonGeeks"
def outer():
  name ="Python"
  def inner():
    global name
    name ="Geeks"
  print("Before calling inner(), value of name in outer():",name)
  inner()
  print("After calling inner(), value of name in outer():",name)

print("Before calling the functions, value of name outside the functions:",name)

outer()

print("After calling the functions, value of name outside the functions:",name)

Output:

Before calling the functions, value of name outside the functions: PythonGeeks
Before calling inner(), value of name in outer(): Python
After calling inner(), value of name in outer(): Python
After calling the functions, value of name outside the functions: Geeks

Quiz on Python Namespace and Scope

Conclusion

In this article, we have learned about namespace and its different types. Then we looked into some cases and keywords used. After this, we discussed the scope and its types. Finally, we saw some interview questions.
Hope you guys understood this article and learned something new. Happy coding!

Did you like our efforts? If Yes, please give PythonGeeks 5 Stars on Google | Facebook

Leave a Reply

Your email address will not be published. Required fields are marked *