Namespaces

Michael Sparks sparks.m at gmail.com
Fri Jan 21 08:26:47 EST 2011


On Jan 21, 10:39 am, sl33k_ <ahsanbag... at gmail.com> wrote:
> What is namespace? And what is built-in namespace?

tl;dr - Namespaces are sets that contain names. You can think of
namespaces as being /like/ boxes. A namespace is therefore an
organisational tool, forming a similar purpose to human names &
surnames - to identify the right value. (eg "Sparks" is a namespace,
"Smith" is another.) The built-in namespace contains all the values
which python understands which you _don't_ define that don't have dots
in. (eg "int", "True", "None")


Looking at this in more detail...


We can create a simple namespace using an empty class Family:

class Family(object):
   pass

Sparks = Family()
Smith = Family()

Now clearly Sparks is a name, and Smith is a name. Those names are
defined to be two different Family objects/values. (I'm going to
deliberately sidestep which namespace "Sparks" and "Smith" sit inside
for the moment.)

The neat trick is that namespaces are values themselves.

In fact the really neat trick is that every value contains a
namespace.

How do I define a name inside a namespace? Suppose I want to define
the name "Michael" as a person inside the Sparks namespace, I can do
that like this:

class Person(object):
   pass

Sparks.Michael = Person()

I can then define the name Michael inside the Smith namespace as well:

Smith.Michael = Person()

As you can see, I can now refer to two different values with the same
name -  "Michael".

This may look a little like sophistry, so let's suppose the Person
we're referring to as Sparks.Michael has an height of 180cm, and a
favourite colour of green, and Smith.Michael has a height of 120cm and
a favourite colour of 120.

In both cases, it makes sense for use to name the height value
"height", and name the favourite colour value as "favourite_colour".
If we did this though ...

height = 180
favourite_colour = "green"
height = 120
favourite_colour = "purple"

.. python would only remember the most recent value of each. By
recognising that every value is a namespace too, we can define those
names inside their namespace.

Sparks.Michael.height = 180
Sparks.Michael.favourite_colour = "green"
Smith.Michael.height = 120
Smith.Michael.favourite_colour = "purple"

Now the question that might arise is this: Given I can rewrite the
examples above like this...

class Family(object):
   pass

class Person(object):
   pass

Sparks = Family()
Smith = Family()
Sparks_Michael = Person()
Smith_Michael = Person()
Sparks_Michael_height = 180
Sparks_Michael_favourite_colour = "green"
Smith_Michael_height = 120
Smith_Michael_favourite_colour = "purple"

... how is this different from before?

Well in this latter version we're not using namespaces to organise our
names. This means that if I want to write a function that prints a
person's height and favourite colour, it has to look like this:

def describe_person(height, favourite_colour):
   print "The person is", height, "cm tall"
   print "Their favourite colour is", favourite_colour

Then if I want to use this, I have to do this:

describe_person(Sparks_Michael_height,
Sparks_Michael_favourite_colour)
describe_person(Smith_Michael_height, Smith_Michael_favourite_colour)

That's quite messy.

What does it look like for the namespace version?

def describe_person(somePerson):
   print "The person is", somePerson.height, "cm tall"
   print "Their favourite colour is", somePerson.favourite_colour

describe_person(Sparks.Michael)
describe_person(Smith.Michael)

describe_person now expects to recieve a single value. Inside that
value's namespace it expects to find the values "height" and "colour",
and just uses them.

As a result, when we use it, rather than passing in each low level
attribute (height, colour) we can work at a more convenient level of
working with People, and the higher level code becomes clearer.

Not only this, if we decide to add an another name to both People ...

Sparks.Michael.Pythonista = True
Sparks.Michael.Pythonista = False

... we can change describe_person to use this:


def describe_person(somePerson):
   print "The person is", somePerson.height, "cm tall"
   print "Their favourite colour is", somePerson.favourite_colour
   if somePerson.Pythonista:
      print "And they like python!"
   else:
      print "They don't know python"

Then our code for describing them remains the same:

describe_person(Sparks.Michael)
describe_person(Smith.Michael)

So far so good I hope.

Namespaces can contain code as well as basic values.

This means we can have ...

tiggles = Cat()
rover = Dog()
jemima = Duck()

tiggles.name = "tiggles"
rover.name = "rover"
jemima.name = "jemima"

... and we can get them all to have some behaviour called "make_noise"
defined by the call to Cat(), Dog(), Duck() inside their namespace,
which allows us to write:

>>> tiggles.make_noise()
Meow!
>>> rover.make_noise()
Woof!
>>> jemima.make_noise()
Quack!

And again that means we can do things like:

def describe_animal(animal):
    print animal.name, "goes", animal.make_noise()

And use it like this:
>>> describe_animal(tiggles)
tiggles goes Meow!
>>> describe_animal(rover)
rover goes Woof!
>>> describe_animal(jemima)
jemima goes Quack!

In addition to defining namespaces though with classes, I can define
them using files.

Suppose I have two files:
   humans.py
   animals.py

And I have another one which is my main program:
  main.py

Furthermore suppose that we decide to put the classes "Family", and
"Person" into humans.py
We also decide to put "Cat", "Dog" and "Duck into animals.py

Inside main.py we need someone of pulling in these names and values in
such a way that we can pull them in cleanly, which is where python's
"import" function comes in.

If we use it like this:

import humans
import animals

This creates two namespaces - humans and animals. The namespace
"humans" contains "Family" and "Person", mirroring the fact the
functionality is defined in the file humans.py. The namespace
"animals" contains "Cat", "Dog" and "Duck", mirroring the fact the
functionality is defined in the file animals.py.

So our code using this would look like this:

Sparks = humans.Family()
Smith = humans.Family()
Sparks.Michael = humans.Person()
Smith.Michael = humans.Person()

tiggles = animals.Cat()
rover = animals.Dog()
jemima = animals.Duck()

This can be a bit clunky if you're doing it a lot, so let's revisit
where I said "I'm going to deliberately sidestep which namespace
"Sparks" and "Smith" sit inside for the moment.".

I mentioned that names like:
   - object
   - list
   - int
   - True

.. ie names that you can use without defining are defined inside a
namespace built-in to python - which is referred to as the built-in
namespace.

In particular, if I type:
>>> object
<type 'object'>
>>> int
<type 'int'>
>>> True
True

Those names are defined from within the built-in namespace.

Where are names like ...
   Sparks
   Smith
   humans
   animals

... being defined ?

Well,it turns out that python (like many other languages) has global
values (amongst others), and that global values are accessed via the
global namespace:

>>> import animals
>>> import humans
>>> Sparks = humans.Family()
>>> Smith = humans.Family()
>>> globals()
{'animals': <module 'animals' from 'animals.py'>,
  'humans': <module 'humans' from 'humans.py'>,
  'Smith': <humans.Family instance at 0xb7d343ac>,
  'Sparks': <humans.Family instance at 0xb7d3420c>,
  '__builtins__': <module '__builtin__' (built-in)>,
  '__package__': None,
  '__name__': '__main__',
  '__doc__': None}

As a result every name sits inside some namespace of some kind. A
namespace is used for organising things, and so namespaces can
themselves be names and treated as values. Inside a namespace a name
can only refer to one value. (Though that value can be a list/tuple/
dict of course, or a piece of behaviour - such as a method or
function)

Python modules form namespaces.
Python classes form namespaces.
Python objects form namespaces.

In the case of import this also explains the fact there are two forms
of import. This version:

import humans
import animals

Simply defines two names, based on the filename containing interesting
functionality, which are namespaces containing other names and is used
as above.

The other looks like this:

from humans import Family, Person
from animals import Cat, Dog, Duck

And still pulls in the same two files, but says "I'm only interested
in these 5 things, and please use them to define the names Family,
Person, Cat, Dog, Duck" in my global namespace so I can use it like
this:

Sparks = Family()
Smith = Family()
Sparks.Michael = Person()
Smith.Michael = Person()

tiggles = Cat()
rover = Dog()
jemima = Duck()

Which is pretty useful.

So what are they?

"Namespaces are one honking great idea -- let's do more of those!"

:-)


Michael.



More information about the Python-list mailing list