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.
X = value
Makes names local: creates or changes name X
in
the current local scope, unless declared global
X
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:
object.X
=
value
Creates or alters the attribute name X
in the
namespace of the object being qualified
object.X
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.