I l@ve RuBoard |
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:
Unqualified names (X) deal with scopes.
Qualified names (object.X) use object namespaces.
Scopes initialize object namespaces (in modules and classes).
Unqualified names follow the LGB rules we outlined for functions in Chapter 4.
Makes names local: creates or changes name X in the current local scope, unless declared global
Looks for name X in the current local scope, then the current global scope, then the built-in scope
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:
Creates or alters the attribute name X in the namespace of the object being qualified
Searches for the attribute name X in the object, then in all accessible classes above it (but not for modules)
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 |