[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