extending methods ?

A

Arnd Baecker

Hi,

the summary of my question is:
is there a way to append commands to a method inherited from
another class?

More verbose: Assume the following situation that I have
a class class_A with several methods.
In each of these methods quite a few computations take place
and several variables are defined.
Now I would like to extend this class to a class_B.
However, instead of overriding a method completely,
I would like to extend the method by basically adding
further commands at the end.

Eg., the code could look like:

class class_A:
def method1(self,x):
y=5*x+1 # create a variable


class class_B(class_A):
appendto method1(self,x):
print y # use variable defined in class_A


I.e. Effictively class_B should "look" like:

class class_B(class_A):
def method1(self,x):
y=5*x+1 # create a variable
print y # use the variable

Instead of this, one could in principle
store all variables defined in
method1 of class_A, eg. with self.y=y
and call in class_B the method1 of class_A.
However, with several variables and several methods
the code will not look nice.
(also efficiency is a bit of concern - presumably it shouldn't -
to me here as in my application the methods
are used to plot dots, circles, triangles etc.
so that speed is really important)

So is there a way to extend methods in the above sense
or is there a better (more pythonic ? ;-) approach to what I want?

Many thanks in advance.

Arnd

P.S.: Sorry if I messed up things on the OO side
(I am a real new-comer to this ...;-).
 
A

Alex Martelli

Arnd said:
Hi,

the summary of my question is:
is there a way to append commands to a method inherited from
another class?

The canonical way to achieve that is to override the method,
and, within the override, call up to the superclass's
implementation.

More verbose: Assume the following situation that I have
a class class_A with several methods.
In each of these methods quite a few computations take place
and several variables are defined.

Ah, no way, then -- local variables of a method (just like
any other function) are totally internal to that method, and
there is absolutely no reasonable way to access them from
the outside.
However, with several variables and several methods
the code will not look nice.

A matter of opinion. I find it much nicer to know that a
local variable is local, and an instance variable is not.
(also efficiency is a bit of concern - presumably it shouldn't -

Right, it shouldn't. Local variables are fast BECAUSE they
are local. If they were non-local -- as you require, in order
to work with them from outside the defining method -- then
they wouldn't be fast.
to me here as in my application the methods
are used to plot dots, circles, triangles etc.
so that speed is really important)

I strongly doubt that the loss of speed due to making some
needed variable non-local is going to be measurable. Taking
your example...:

[alex@lancelot python2.3]$ python timeit.py \
-s 'class A:' \
-s ' def method1(self, x): y = 5 * x + 1' \
-s ' def method2(self, x): self.y = 5 * x + 1' \
-s 'a=A()' \
'a.method1(23)'
1000000 loops, best of 3: 1.47 usec per loop

and the same with method2 instead: 1.66 usec per loop.

What makes you think that a "slow-down" of 190 nanoseconds,
i.e. about 13% on this method call, is gonna be SO crucial?

And if you ARE working in an environment where every single
nanosecond matter, then what about...:

[alex@lancelot python2.3]$ python timeit.py \
-s 'class A:' \
-s ' def method1(self, x): y = 5 * x + 1' \
-s ' def method2(self, x): self.y = 5 * x + 1' \
-s 'a=A()' \ - -s 'meth=a.method2' \
'meth(23)'
1000000 loops, best of 3: 1.25 usec per loop

See? Extracting the bound method once and for all saves
you a whopping *410* nanoseconds per call, compensating
the 190 "lost" by making instance variables where you need
them *and then some*. In other words, there are ways and
means to squeeze nanoseconds out of some Python bottleneck
that do not necessarily require using local variables where
you need instance or other non-local ones!

So is there a way to extend methods in the above sense
or is there a better (more pythonic ? ;-) approach to what I want?

There is no pythonic way to treat local variables as non-local.
(There MAY be horrible bytecode hacks exploiting hooks that are
meant for debugging only -- but THOSE *WILL* slow you down
SERIOUSLY...).


Alex
 
D

David C. Fox

Arnd said:
Hi,

the summary of my question is:
is there a way to append commands to a method inherited from
another class?

More verbose: Assume the following situation that I have
a class class_A with several methods.
In each of these methods quite a few computations take place
and several variables are defined.
Now I would like to extend this class to a class_B.
However, instead of overriding a method completely,
I would like to extend the method by basically adding
further commands at the end.

Eg., the code could look like:

class class_A:
def method1(self,x):
y=5*x+1 # create a variable


class class_B(class_A):
appendto method1(self,x):
print y # use variable defined in class_A


I.e. Effictively class_B should "look" like:

class class_B(class_A):
def method1(self,x):
y=5*x+1 # create a variable
print y # use the variable

If you really want to do this, you are probably better off doing it
explicitly. For example


class A:
def store_locals(self, local_variables, keep_locals):
if keep_locals is None:
return
keep_locals.update(local_variables)

def m(self, x, keep_locals = None):
"""If you want to keep the local variables of this method,
specify a dictionary for keep_locals
"""
y = 5*x+1
self.store_locals(locals(), keep_locals)


class C(A):
def m(self, x, keep_locals = None):
if keep_locals is None:
keep_locals = {}
v = A.m(self, x, keep_locals = keep_locals)
print 'y was ', keep_locals['y']
return v

P.S.: Sorry if I messed up things on the OO side
(I am a real new-comer to this ...;-).

Perhaps if you tell us more about why you want to do this, we could come
up with a better OO solution.

David
 
S

Stephen Horne

the summary of my question is:
is there a way to append commands to a method inherited from
another class?

If you can call...

instance.method (arg1, ...)

then you can equivalently call...

classname.method (instance, arg1, ...)

You can use this in your subclasses method to call the method from a
specified base class (with multiple inheritance there may be more than
one base). For example...
.... def dostuff (self) :
.... print "running A.dostuff"
........ def dostuff (self) :
.... print "running B.dostuff"
.... A.dostuff (self)
....running B.dostuff
running A.dostuff
 
C

Carlo v. Dango

Actually this seems exactly the sort of thing for which aspect
oriented programming was developed.

excuse me, but that is utterly and completely rubbish! :) Specializing
methods is actually very useful, but I've only seen it in the language
Beta (well I'm certain it could be achieved in Simula 67 as well). In
simula classes and methods has been unified into the notion of a
"pattern". So since you can specialize classes, you now also can
specialize methods using this pattern construct.

AOP was designed to be able to define CROSS-CUTTING entities crosscutting
at least 2 inheritance hierachies.

You should all at least try to read up on the Beta language and grasp its
powerful idea of the pattern construct!

-carlo van dango
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,968
Messages
2,570,149
Members
46,695
Latest member
StanleyDri

Latest Threads

Top