I l@ve RuBoard Previous Section Next Section

6.7 Namespace Rules: The Whole Story

Now that we've seen class and instance objects, the Python namespace story is complete; for reference, let's quickly summarize all the rules used to resolve names. The first things you need to remember are that qualified and unqualified names are treated differently, and that some scopes serve to initialize object namespaces:

6.7.1 Unqualified Names: Global Unless Assigned

Unqualified names follow the LGB rules we outlined for functions in Chapter 4.

Assignment: X = value

Makes names local: creates or changes name X in the current local scope, unless declared global

Reference: X

Looks for name X in the current local scope, then the current global scope, then the built-in scope

6.7.2 Qualified Names: Object Namespaces

Q ualified names refer to attributes of specific objects and obey the rules we met when discussing modules. For instance and class objects, the reference rules are augmented to include the inheritance search procedure:

Assignment: object.X = value

Creates or alters the attribute name X in the namespace of the object being qualified

Reference: object.X

Searches for the attribute name X in the object, then in all accessible classes above it (but not for modules)

6.7.3 N amespace Dictionaries

Finally, in Chapter 5, we saw that module namespaces were actually implemented as dictionaries and exposed with the built-in __ dict _ _ attribute. The same holds for class and instance objects: qualification is really a dictionary indexing internally, and attribute inheritance is just a matter of searching linked dictionaries.

The following example traces the way namespace dictionaries grow when classes are involved. The main thing to notice is this: whenever an attribute of self is assigned in one of the two classes, it creates (or changes) an attribute in the instance's namespace dictionary, not the class's. Instance object namespaces record data that can vary from instance to instance; they also have links to class namespaces that are followed by inheritance lookups. For example, X.hello is ultimately found in the super class's namespace dictionary.

>>> class super:
...     def hello(self):
...         self.data1 = "spam"
...
>>> class sub(super):
...     def howdy(self):
...         self.data2 = "eggs"
...
>>> X = sub()          # make a new namespace (dictionary)
>>> X.__dict__
{}
>>> X.hello()          # changes instance namespace
>>> X.__dict__
{'data1': 'spam'}

>>> X.howdy()          # changes instance namespace
>>> X.__dict__
{'data2': 'eggs', 'data1': 'spam'}

>>> super.__dict__
{'hello': <function hello at 88d9b0>, '__doc__': None}

>>> sub.__dict__
{'__doc__': None, 'howdy': <function howdy at 88ea20>}

>>> X.data3 = "toast"
>>> X.__dict__
{'data3': 'toast', 'data2': 'eggs', 'data1': 'spam'}

Note that the dir function we met in Chapter 1 and Chapter 2 works on class and instance objects too. In fact, it works on anything with attributes. dir(object) returns the same list as a object. __ dict __ .keys() call.

I l@ve RuBoard Previous Section Next Section