Learning Python - Mark Lutz [417]
return result
Note the use of a generator expression to direct the recursive calls for superclasses; it’s activated by the nested string join method. Also see how this version uses the Python 3.0 and 2.6 string format method instead of % formatting expressions, to make substitutions clearer; when many substitutions are applied like this, explicit argument numbers may make the code easier to decipher. In short, in this version we exchange the first of the following lines for the second:
return ' return ' Now, change testmixin.py to inherit from this new class again to test: class Sub(Super, ListTree): # Mix in a __str__ The file’s tree-sketcher output in Python 2.6 is then as follows: C:\misc> c:\python26\python testmixin.py data1=spam data2=eggs data3=42 .... __init__=<> __module__=<> spam= ........ __init__=<> __module__=<> ham= ........> ........ _ListTree__listclass= __doc__=<> __module__=<> __str__=<> ........> ....> > Notice in this output how methods are unbound now under 2.6, because we fetch them from classes directly, instead of from instances. Also observe how the lister’s __visited table has its name mangled in the instance’s attribute dictionary; unless we’re very unlucky, this won’t clash with other data there. Under Python 3.0, we get extra attributes and superclasses again. Notice that unbound methods are simple functions in 3.0, as described in an earlier note in this chapter (and that again, I’ve deleted most built-in attributes in object to save space here; run this on your own for the complete listing): C:\misc> c:\python30\python testmixin.py data1=spam data2=eggs data3=42 .... __init__=<> __module__=<> spam= ........ __doc__=<> __init__=<> __module__=<> __weakref__=<> ham= ............ __delattr__=<> __doc__=<> __eq__=<> ...more omitted... __repr__=<> __setattr__=<> __sizeof__=<> __str__=<> __subclasshook__=<> ............> ........> ........ _ListTree__listclass= __dict__=<> __doc__=<> __module__=<> __str__=<> __weakref__=<> ............ ........> ....> > This version avoids listing the same class object twice by keeping a table of classes visited so far (this is why an object’s id is included—to serve as a key for a previously displayed item). Like the transitive module reloader of Chapter 24, a dictionary works to avoid repeats and cycles here because class objects may be dictionary keys; a set would provide similar functionality. This version also takes care to avoid large internal objects by skipping __X__ names again. If you comment out the test for these names, their values will display normally. Here’s an excerpt from the output in 2.6 with this temporary change made (it’s much larger in its entirety, and it gets even worse in 3.0, which is why these names are probably better skipped!): C:\misc> c:\python26\python testmixin.py ...more omitted... ........ _ListTree__listclass= __doc__= Mix-in that returns the __str__ trace of the entire class tree and all its objects' attrs at and above self; run by print, str