Online Book Reader

Home Category

Learning Python - Mark Lutz [384]

By Root 1487 0
namespace dictionary, which starts out empty and can record completely different attributes than those recorded by the namespace dictionaries of other instances of the same class.

Because attributes are actually dictionary keys inside Python, there are really two ways to fetch and assign their values—by qualification, or by key indexing:

>>> X.data1, X.__dict__['data1']

('spam', 'spam')

>>> X.data3 = 'toast'

>>> X.__dict__

{'data1': 'spam', 'data3': 'toast', 'data2': 'eggs'}

>>> X.__dict__['data3'] = 'ham'

>>> X.data3

'ham'

This equivalence applies only to attributes actually attached to the instance, though. Because attribute fetch qualification also performs an inheritance search, it can access attributes that namespace dictionary indexing cannot. The inherited attribute X.hello, for instance, cannot be accessed by X.__dict__['hello'].

Finally, here is the built-in dir function we met in Chapters 4 and 15 at work on class and instance objects. This function works on anything with attributes: dir(object) is similar to an object.__dict__.keys() call. Notice, though, that dir sorts its list and includes some system attributes. As of Python 2.2, dir also collects inherited attributes automatically, and in 3.0 it includes names inherited from the object class that is an implied superclass of all classes:[67]

>>> X.__dict__, Y.__dict__

({'data1': 'spam', 'data3': 'ham', 'data2': 'eggs'}, {})

>>> list(X.__dict__.keys()) # Need list in 3.0

['data1', 'data3', 'data2']

# In Python 2.6:

>>>> dir(X)

['__doc__', '__module__', 'data1', 'data2', 'data3', 'hello', 'hola']

>>> dir(sub)

['__doc__', '__module__', 'hello', 'hola']

>>> dir(super)

['__doc__', '__module__', 'hello']

# In Python 3.0:

>>> dir(X)

['__class__', '__delattr__', '__dict__', '__doc__', '__eq__', '__format__',

...more omitted...

'data1', 'data2', 'data3', 'hello', 'hola']

>>> dir(sub)

['__class__', '__delattr__', '__dict__', '__doc__', '__eq__', '__format__',

...more omitted...

'hello', 'hola']

>>> dir(super)

['__class__', '__delattr__', '__dict__', '__doc__', '__eq__', '__format__',

...more omitted...

'hello'

]

Experiment with these special attributes on your own to get a better feel for how namespaces actually do their attribute business. Even if you will never use these in the kinds of programs you write, seeing that they are just normal dictionaries will help demystify the notion of namespaces in general.

Namespace Links

The prior section introduced the special __class__ and __bases__ instance and class attributes, without really explaining why you might care about them. In short, these attributes allow you to inspect inheritance hierarchies within your own code. For example, they can be used to display a class tree, as in the following example:

# classtree.py

"""

Climb inheritance trees using namespace links,

displaying higher superclasses with indentation

"""

def classtree(cls, indent):

print('.' * indent + cls.__name__) # Print class name here

for supercls in cls.__bases__: # Recur to all superclasses

classtree(supercls, indent+3) # May visit super > once

def instancetree(inst):

print('Tree of %s' % inst) # Show instance

classtree(inst.__class__, 3) # Climb to its class

def selftest():

class A: pass

class B(A): pass

class C(A): pass

class D(B,C): pass

class E: pass

class F(D,E): pass

instancetree(B())

instancetree(F())

if __name__ == '__main__': selftest()

The classtree function in this script is recursive—it prints a class’s name using __name__, then climbs up to the superclasses by calling itself. This allows the function to traverse arbitrarily shaped class trees; the recursion climbs to the top, and stops at root superclasses that have empty __bases__ attributes. When using recursion, each active level of a function gets its own copy of the local scope; here, this means that cls and indent are different at each classtree level.

Most of this file is self-test code. When run standalone in Python 3.0, it builds an empty class tree, makes two instances from it,

Return Main Page Previous Page Next Page

®Online Book Reader