[Python-talk] Un-inheriting

Bill Freeman f at ke1g.mv.com
Sat Mar 31 09:18:32 EDT 2007


Kent Johnson writes:
 > Bill Freeman wrote:
 > > Suppose that you have a base class foo providing a bunch of stuff
 > > (methods, constants, (intended to be) constant dictionaries, etc.: A,
 > > B, C, D, E, F, G, H...
 > > 
 > > You have a class bar that needs to implement 80% of that
 > > functionality, so it makes sense to derive from foo.  Bar overrides,
 > > say, 15% of the other features, and implements a bunch of new stuff:
 > > W, X, Y, Z.  Still a great case for inheritance.
 > > 
 > > But bar doesn't need member function A.  In fact, bar should not have
 > > A.  Since A is a method, a practical solution is to implement an A in
 > > bar that simply raises a suitable AttributeError ("bar instance has no
 > > attribute 'A'").
 > > 
 > > But this is unsatisfactory under introspection.  Further, if what you
 > > wanted to hide is not a method, it doesn't work at all.
 > > 
 > > There is renaming foo to fooBase, foo from that, where the
 > > implementation of A is moved to foo, and bar inherits from fooBase.
 > > Python's multiple inheritance capabilities makes this feasible, even
 > > with more complex structures (bar is a foo without an A, ugh is a foo
 > > without a B, bletch is a foo without a C,...).  I'm not sure that this
 > > makes for the most readable code in all cases.
 > 
 > This sounds like a reasonable solution. Having bar inherit from foo is 
 > bad design, because "bar is-a foo" is not true.

Yeah.  But bar is soooo close to being a foo.  ;^)

 > > 
 > > One could, I suppose, override __getattr__() and __setattr__() to
 > > suppress A, but won't that affects performance on all attribute
 > > accesses?
 > 
 > This won't work. __getatttr__() is only called when normal attribute 
 > lookup fails. With new-style classes you can override __getattribute__() 
 > to do what you want.
 > 
 > It sounds like you are using inheritance purely for code sharing, not 
 > for any value as a conceptual model. You might consider alternatives.
 > 
 > You could define mixin classes with subsets of the functions you need. 
 > This is just a different way to think about the multiple-inheritance 
 > solution. You could have classes ImplementsA, ImplementsBCDEFGH, 
 > ImplementsWXYZ, and
 > class foo(ImplementsA, ImplementsBCDEFGH)
 > class bar(ImplementsBCDEFGH, ImplementsWXYZ)
 > 
 > etc...hopefully with better names than this.

And that's probably what I'll knuckle down and do.  I have the luxury
because its all my code.  But what about folks who are based on an
externally supplied, maintained, and updated package to provide foo?
Re-implement every time there's an update to foo?

 > 
 > Do the different methods need access to the instance data or could they 
 > be written as standalone functions? Perhaps you could put ABCD... into 
 > one or more utility classes as standalone functions and manually 
 > delegate to them. Or you could put them into helper classes and 
 > automatically delegate to them using __getattr__(). (Yes, this will have 
 > an impact on performance. I don't know how much. My guess is it would 
 > not be more than the cost of a few function calls. Is this code 
 > time-critical or are you making up a performance requirement?)

They do need instance data.  Of course that doesn't prevent standalone
functions from being passed a class instance, or the appropriate data,
but you loose the clarity of the "self.method()" construct.

And performance probably won't matter, especially since there's a
serial connection involved.  But I'm an old timer, and it goes against
the grain to throw away performance if there's a clean alternative.
(Do those python cell phones have serial ports?)

 > > 
 > > bar could define A with:
 > > 	A=property()
 > > This makes A return an attribute error for any kind of vanilla access.
 > > It doesn't work for classic classes (according to the documents), and
 > > I was hoping to get away with classic classes to maximize the number
 > > of places where this code would just work, but that's probably being
 > > overly fussy.
 > 
 > Properties don't work with classic classes. They give the appearance of 
 > working in some situations. Don't be fooled! They don't work.

Yes, that's what the documents said.

 > Kent

Bill


More information about the Python-talk mailing list