[Tutor] design questions: pythonic approach to ostriches
Brian van den Broek
bvande at po-box.mcgill.ca
Sat Apr 23 18:19:20 CEST 2005
Hi all,
I am wondering about the Pythonic way to handle the problem of
ostriches, emus, and penguins. (I cannot recall from where I got the
example.)
Here's what I mean:
class Bird(object):
def fly(self):
# flying logic here
def lay(self):
# egg-laying logic here
# more bird methods
class Ostrich(Bird):
# ostriches can't fly, so what to do?
I've explored a number of solutions; here they are with what I see as
to cons and problems:
The simplest thing is to emulate the ostrich and pretend the problem
doesn't exist. But, putting one's head in the sand looks likely to
cause troubles in that this route break encapsulation, requiring
callers to know enough not to call the fly method of an ostrich. So,
that's no good.
class Ostrich(Bird):
def fly(self):
pass
seems only marginally better, in that it gives the external appearance
of flight, whereas what is needed is a "Hey, I don't fly" signal.
The next thought was to over-ride Ostrich.fly as
def fly(self):
raise NotImplementedError
That seems better, but also a bit confusing; the way I understand it,
NotImplementedError is, in the first instance, for abstract classes or
for marking work in progress. But Ostrich.fly doesn't fit either case.
That makes me think to define a custom exception, say
class OstrichError(NotImplementedError):
'''A custom exception for cases of the "Ostrich problem".
Intended to be raised by methods in a subclass over-riding methods
of the parent which don't make sense for the subclass to actually
implement.'''
def __init__(self):
NotImplementedError.__init__(self)
But, since the problem isn't one that my penetrating genius
discovered, I am inclined to think that were this the ideal solution,
there'd be a (better named) exception class builtin to Python already.
A complicated class hierarchy like
class Bird(object):
# bird logic
class FlyingBird(Bird):
def fly(self):
# flying logic here
class FlightlessBird(Bird):
# any particularly flightless logic here
class Ostrich(FlightlessBird):
# ostrich logic
seems an invitation to difficulty. My analogy will soon break, but
some birds build nests and sing, others, no so much, etc. Flat is soon
to give way to deeply nested.
I also tried to delete the inherited Bird.fly method within
Ostrich.__init__, but
class Ostrich(Bird):
def __init__(self):
del self.__dict__['fly']
raises a KeyError, whereas
def __init__(self):
del Ostrich.__dict__['fly']
raises:
TypeError: object does not support item deletion
Do I have the syntax of the last approach wrong? Or is there no way to
remove a method from a class? If the latter, what to do about
flightless fowl?
Thanks and best,
Brian vdB
More information about the Tutor
mailing list