Python Namespace
Namespaces are a fundamental idea in Python and can be very helpful in structuring and organizing your code. However, namespaces might be a somewhat difficult concept to grasp and get used to if you’re new to programming or even coming from another programming language (in my case, Java). Here’s my attempt to make namespaces just a little easier to understand.

For example, when we do the assignment a = 2, here 2 is an object stored in memory and a is the name we associate it with. We can get the address (in RAM) of some object through the built-in function, id(). Let's check it.
>>> a = 2
>>> print('id(2) =', id(2))
id(2) = 1735878800
>>> print('id(a) =', id(a))
id(a) = 1735878800

What is a namespace?

A namespace containing all the built-in names is created when we start the Python interpreter and exists as long we don't exit. A name in Python is roughly analogous to a variable in just about any other language, but with a few extras. First of, because of Python’s dynamic nature, you can apply a name to just about anything.

Different namespaces can co-exist at a given time but are completely isolated.

This is the reason that built-in functions like id(), print() etc. are always available to us from any part of the program. Each module creates its own global namespace. You can of course give names to values.

>>> x = 9
>>> x = 'FTL'
>>> x = [1,2,3,4,5,6,7]

Three different types of object at different instances. Functions are objects too, so a name can refer to them as well.

def func():
    print ('This is a sample function')
f = func

Python Variable Scopes

Although there are various unique namespaces defined, we may not be able to access all of them from every part of the program.

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

  • Scope of the current function which has local names
  • Scope of the module which has global names
  • Outermost scope which has built-in names

For example, the following code is perfectly legal in Python :

>>> var = 18
>>> var = "This is a sample string"
>>> var = [2, 4, 6, 8, 10, 12, 14]

Python Variable Scopes and Namespace

Here, the variable a is in the global namespace. Variable b is in the local namespace of outer_function() and c is in the nested local namespace of inner_function().

When we are in inner_function(), c is local to us, b is nonlocal and a is global. We can read as well as assign new values to c but can only read b and c from inner_function().

>>> def outer_function():
	global a
	a = 20
	def inner_function():
		global a
		a = 30
		print('a =',a)
		print('a =',a)
		a = 10

>>> print('a =',a)
a = 2