giveRaise
method of a
Manager
in-
stance, it will run this custom version, which tacks on the extra bonus. So what’s wrong
with something that runs correctly?
The problem here is a very general one: any time you copy code with cut and paste,
you essentially
double
your maintenance effort in the future. Think about it: because
we copied the original version, if we ever have to change the way raises are given (and
we probably will), we’ll have to change the code in
two
places, not one. Although this
is a small and artificial example, it’s also representative of a universal issue—any time
you’re tempted to program by copying code this way, you probably want to look for a
better approach.
Augmenting Methods: The Good Way
What we really want to do here is somehow
augment
the original
giveRaise
, instead of
replacing it altogether. The
good way
to do that in Python is by calling to the original
version directly, with augmented arguments, like this:
class Manager(Person):
def giveRaise(self, percent, bonus=.10):
Person.giveRaise(self, percent + bonus)
# Good: augment original
656
|
Chapter 27:
A More Realistic Example
Copyright © ${Date}. ${Publisher}. All rights reserved.

This code leverages the fact that a class method can always be called either through an
instance
(the usual way, where Python sends the instance to the
self
argument auto-
matically) or through the
class
(the less common scheme, where you must pass the
instance manually). In more symbolic terms, recall that a normal method call of this
form:
instance
.
method
(
args...
)
is automatically translated by Python into this equivalent form:
class
.
method
(
instance
,
args...
)
where the class containing the method to be run is determined by the inheritance search
rule applied to the method’s name. You can code
either
form in your script, but there
is a slight asymmetry between the two—you must remember to pass along the instance
manually if you call through the class directly. The method always needs a subject
instance one way or another, and Python provides it automatically only for calls made
through an instance. For calls through the class name, you need to send an instance to
self
yourself; for code inside a method like
giveRaise
,
self
already
is
the subject of the
call, and hence the instance to pass along.
Calling through the class directly effectively subverts inheritance and kicks the call
higher up the class tree to run a specific version. In our case, we can use this technique
to invoke the default
giveRaise
in
Person
, even though it’s been redefined at the
Manager
level. In some sense, we
must
call through
Person
this way, because a
self.giveRaise()
inside
Manager
’s
giveRaise
code would loop—since
self
already is a
Manager
,
self.giveRaise()
would resolve again to
Manager.giveRaise
, and so on and so
forth until available memory is exhausted.


You've reached the end of your free preview.
Want to read all 214 pages?
- Fall '15