[Tutor] namespace confusion

Kent Johnson kent37 at tds.net
Thu Jan 19 03:03:27 CET 2006


Christopher Spears wrote:
> Let's say I have two classes:
> 
> 
>>>>class super:
> 
> ...     def hello(self):
> ...         self.data1 = 'spam'
> ...
> 
>>>>class sub(super):
> 
> ...     def hola(self):
> ...         self.data2 = 'eggs'
> ...
> 
> Now let's look in the classes' namespaces using
> __dict__:

First a point of terminology - classes and objects don't have 
namespaces, they have attributes. Namespaces are where variables are 
looked up, not attributes. Names are looked up in the local namespace, 
any enclosing namespaces, the module (global) namespace and the built-in 
namespace.

What you are talking about is attributes and attribute lookup. Attribute 
lookup can seem quite simple but in fact when you look under the hood 
there is a lot going on. Python in a Nutshell says, "Attribute 
references...have fairly rich semantics in Python". I think that is an 
understatement.

So I'll oversimplify to start. When you ask Python for the value of 
foo.bar, first it looks up foo in the namespace hierarchy as described 
above. Then, given the value of foo, it looks for a bar attribute. The 
first place to look is in foo.__dict__. If it is not found there, then 
the class of foo is tried - foo.__class__.__dict__. Failing that, each 
of the base classes of foo.__class__ is searched, and their base classes 
up the inheritance chain.

This search is performed dynamically every time you ask for foo.bar - 
it's quite possible that bar will be found in a different location on 
two different searches. In time-critical code it's common to optimize 
out this lookup by assigning a method to a local variable, for example.

In your example, hola is an attribute of sub and appears in 
sub.__dict__. hello is an attribute of super and appears in 
super.__dict__. When you access sub.hola, it is found in sub.__dict__. 
When you access sub.hello, the lookup in sub.__dict__ fails so 
super.__dict__ is tried and hello is found there.

dir() is a convenience function that attempts to show the some of the 
attributes that are accessible from the object you pass to it.

As I said, the above is a gross oversimplification. It is mostly true 
for common cases. I don't want to attempt a complete correct explanation 
but I will say that attribute lookup is also affected by __getattr__, 
__getattribute__, __slots__, properties, and whether the attribute is a 
special name.

Unfortunately I don't know of any single place where all of this is 
written down.

Kent
> 
> 
>>>>sub.__dict__
> 
> {'__module__': '__main__', '__doc__': None, 'hola':
> <function hola at 0x403954fc>}
> 
> 
>>>>super.__dict__
> 
> {'__module__': '__main__', 'hello': <function hello at
> 0x4039548c>, '__doc__': None}
> 
> I was first confused why 'hello' did not appear in sub
> as well.  Then I read about dir():
> 
> 
>>>>dir(sub)
> 
> ['__doc__', '__module__', 'hello', 'hola']
> 
> 
>>>>dir(super)
> 
> ['__doc__', '__module__', 'hello']
> 
> The above result makes more sense to me.  Why doesn't
> __dict__ give the same response as dir()?  How come I
> don't see super in sub's namespace?
> 
> -Chris
> _______________________________________________
> Tutor maillist  -  Tutor at python.org
> http://mail.python.org/mailman/listinfo/tutor
> 
> 




More information about the Tutor mailing list