Variable inheritance
Alex Martelli
aleaxit at yahoo.com
Tue May 22 16:18:46 EDT 2001
"Roman Suzi" <rnd at onego.ru> writes:
...
> This gives better granularity than MI could provide.
Feature-granularity is a completely orthogonal issue
from one of implementation -- it's part of the specs!
The user in my example is picking a bridge-bidding
system out of a set of agreements, and some subsets
just MUST go together or are incompatible -- this is
my decision as an application-field expert analyst,
and I won't LET it be dictated by implementation level
concerns! Do YOU let the coding tail wag the dog
of specs?!
> Just pick your fetures directly, why do you need
> inheritance?
As an implementation-level decision, I don't want to
have to code selection logic in my application-level
objects, given that the language gives me a much
better mechanism in its polymorphism implementation
via MI. Isn't that obvious? Why re-do something the
language does perfectly well?!
The user is going to write scripts in some language or
other that use the 'objects' he has created, and other
framework-level objects I supply. As it happens, as
the language in question I have chosen Python, as I
happen to like it a LOT (don't you?), so the objects
must be Python-callable (some stereotypical simple
scripts may be written via code generator, but, even
then, inheritance is the RIGHT code-reuse technique:
the user does NOT edit the code-generator-written
code, he or she INHERITS from classes built by the
code-generator if any tweaking is needed... as a
matter of course, I should say!).
So why should each object the user sees implement
a __getattr__ and duplicate the same search process
that Python ALREADY gives me for free, provided
only that I use inheritance?! *WHAT IS SUPPOSED
TO BE THE ADVANTAGE* of recoding from scratch, in
Python, mechanisms that are already perfectly well
provided by the language infrastructure?!
> >I don't see how aggregation and delegation would be easier
> >to implement and maintain than this simple framework.
>
> It depends. Python has great functional capabilities
> to make container-writing (with proper dispatching
> of messages) very easy.
Sure. And the simplest of such functional capability
is called INHERITANCE -- the premier code reuse
technique.
> I can't agree Python's MI is a way to do HAS-A
> relations. It seems to me like using only
"Has-A"? Who cares about that?! All I ever want from
inheritance (and overriding, etc) is BEHAVES-LIKE.
An elementary bridge-hand-evaluation class, for
example, will have some kinds of behaviors such
as:
class SimpleEvaluate:
def high_card_points(self):
return reduce(operator.add,
map(self.honor_value, self.card_ranks))
def shape_points(self):
return reduce(operator.add,
map(self.lengh_value, self.suit_lengths))
def length_value(self, suitlen):
return max(0, 3-suitlen)
def honor_value(self, cardval):
return max(0, cardval-10) #a=14, k=13, ...
def dh_points(self):
return self.high_card_points()+self.shape_points()
# and so on
This is the floor-level -- the way Goren counted HCP's
and shape. Now visit http://www.gg.caltech.edu/~jeff/knr.txt
and see one set of tweaks that can be applied to make
this more accurate. I have my own ideas, and the end-user
is likely to have his or her own (no two bridge-players agree
on ALL...!-). Clearly I need to allow "override and call the
overridden method" so no need to COPY AND PASTE (horror!)
all this code is needed. E.g., one popular tweak would be
to subtract a point for a totally flat hand (4-3-3-3) and add
one for a hand with a very long suit. With no need to copy
and paste, the user of the framework just needs to code:
class FlatBad_LongGood(SimpleEvaluate):
def shape_points(self):
baseval = SimpleEvaluate.shape_points(self)
shortest = reduce(min, self.suit_lengths)
longest = reduce(max, self.suit_lengths)
if shortest>2: baseval -= 1
if longest>6: baseval += 1
return baseval
And meanwhile, another popular tweak is liking aces:
class AceIsNice(SimpleEvaluate):
def high_card_points(self):
baseval = SimpleEvaluate.high_card_points(self)
aces = self.card_ranks.count(14)
if aces==0: baseval-=1
elif aces==4: baseval+=1
return baseval
So how does another use COMBINE both of these behavioral
tweaks? *COPY AND PASTE*?!
The *OBVIOUS* way, of which I STILL have seen no hint
at all from you why it should be AT ALL 'bad' in Python:
class SmartEvaluate(AceIsNice, FlatBad_LongGood):
pass
That's it -- period! When the user in his or her scripts
needs the D+H (distribution+honor) points, he or she
just calls self.dh_points(), and inheritance and overrides
ensure the polymorphic call will just do the right thing.
*WHAT ADVANTAGE DO YOU ASSERT* that would make
it worthwhile to have the user start coding delegation
and search-boilerplate, etc, etc, to duplicate all that the
Python interpreter is ALREADY giving him/her for free?!
> from A import *
> from B import *
> ...
> from X import *
>
> applied at the class level.
It's chaining of dictionaries, not .update calls as this
technique would do. Not that there's anything that is
intrinsically bad in doing a clever series of .update calls
on a dictionary, but a typical override (depending on
the field of application) may have to call the method
that is being overridden, and .update and equivalents
don't support that as well as dict-chaining does.
> BTW, is there any book or other source which explains
> OOP python-wise?
I think Mark Lutz' 2nd edition of Programming Python
may be one answer to this question. But no, as far as
I know (and I should), there is no Python equivalent of
such books as "Object-Oriented Software Construction",
"The Smalltalk Design Pattern Companion", Fowler's
"Refactoring", and so on. Yes, there SHOULD be an
"Object-Oriented Programming Through Python" or the
equivalent. The Cookbook chapter on OO (when the
Cookbook comes out... don't hold your breath:-) may
help, though it will be mostly concrete snippets of
code _illustrating_ issues, concerns, techniques, and
actual applications, rather than general-purpose design
level considerations (do start by peeking at the current
early state of the Cookbook on the ActiveState site... all
are invited to participate, so, why not offer a recipe that
shows the huge advantages you claim can be had by
eschewing multiple inheritance?-).
Alex
_________________________________________________________
Do You Yahoo!?
Get your free @yahoo.com address at http://mail.yahoo.com
More information about the Python-list
mailing list