Online Book Reader

Home Category

Learning Python - Mark Lutz [415]

By Root 1885 0
access to self

Super.__init__(self)

self.data2 = 'eggs' # More instance attrs

self.data3 = 42

def spam(self): # Define another method here

pass

if __name__ == '__main__':

X = Sub()

print(X) # Run mixed-in __str__

Here, Sub inherits names from both Super and ListInstance; it’s a composite of its own names and names in both its superclasses. When you make a Sub instance and print it, you automatically get the custom representation mixed in from ListInstance (in this case, this script’s output is the same under both Python 3.0 and 2.6, except for object addresses):

C:\misc> C:\python30\python testmixin.py

name data1=spam

name data2=eggs

name data3=42

>

ListInstance works in any class it’s mixed into because self refers to an instance of the subclass that pulls this class in, whatever that may be. In a sense, mix-in classes are the class equivalent of modules—packages of methods useful in a variety of clients. For example, here is Lister working again in single-inheritance mode on a different class’s instances, with import and attributes set outside the class:

>>> import lister

>>> class C(lister.ListInstance): pass

...

>>> x = C()

>>> x.a = 1; x.b = 2; x.c = 3

>>> print(x)

name a=1

name b=2

name c=3

>

Besides the utility they provide, mix-ins optimize code maintenance, like all classes do. For example, if you later decide to extend ListInstance’s __str__ to also print all the class attributes that an instance inherits, you’re safe; because it’s an inherited method, changing __str__ automatically updates the display of each subclass that imports the class and mixes it in. Since it’s now officially “later,” let’s move on to the next section to see what such an extension might look like.

Listing inherited attributes with dir

As it is, our Lister mix-in displays instance attributes only (i.e., names attached to the instance object itself). It’s trivial to extend the class to display all the attributes accessible from an instance, though—both its own and those it inherits from its classes. The trick is to use the dir built-in function instead of scanning the instance’s __dict__ dictionary; the latter holds instance attributes only, but the former also collects all inherited attributes in Python 2.2 and later.

The following mutation codes this scheme; I’ve renamed it to facilitate simple testing, but if this were to replace the original version, all existing clients would pick up the new display automatically:

# File lister.py, continued

class ListInherited:

"""

Use dir() to collect both instance attrs and names

inherited from its classes; Python 3.0 shows more

names than 2.6 because of the implied object superclass

in the new-style class model; getattr() fetches inherited

names not in self.__dict__; use __str__, not __repr__,

or else this loops when printing bound methods!

"""

def __str__(self):

return '' % (

self.__class__.__name__, # My class's name

id(self), # My address

self.__attrnames()) # name=value list

def __attrnames(self):

result = ''

for attr in dir(self): # Instance dir()

if attr[:2] == '__' and attr[-2:] == '__': # Skip internals

result += '\tname %s=<>\n' % attr

else:

result += '\tname %s=%s\n' % (attr, getattr(self, attr))

return result

Notice that this code skips __X__ names’ values; most of these are internal names that we don’t generally care about in a generic listing like this. This version also must use the getattr built-in function to fetch attributes by name string instead of using instance attribute dictionary indexing—getattr employs the inheritance search protocol, and some of the names we’re listing here are not stored on the instance itself.

To test the new version, change the testmixin.py file to use this new class instead:

class Sub(Super, ListInherited): # Mix in a __str__

This file’s output varies per release. In Python 2.6, we get the following; notice the name mangling at work in the lister’s method name (I shortened

Return Main Page Previous Page Next Page

®Online Book Reader