Reusing object methods?

Bengt Richter bokr at oz.net
Fri Apr 29 17:38:17 EDT 2005


On Fri, 29 Apr 2005 19:45:54 +0200, Ivan Voras <ivoras at _-_fer.hr> wrote:

>
>Can this be done: (this example doesn't work)
>
>----
>class A:
>
>     def a_lengthy_method(self, params):
>          # do some work depending only on data in self and params
>
>class B:
>
>     def __init__(self):
>         self.a_lengthy_method = A.a_lengthy_method
>         # I know that data in "self" of class B object is compatible
>         # with that of class A object
>----
>
>I want to 'reuse' the same method from class A in class B, and without 
>introducing a common ancestor for both of them - is this possible in an 
>elegant, straightforward way?

Your design intent is not quite clear to me, since you are trying to
capture the A method from B's instance initialization. If it is to be
a method of B, why not put the code in the class body of B instead
of in B.__init__, whose concern is B instances, not the B class (at least normally).
OTOH, if you really want an "instance-method" as an attribute of a B instance, see
class B below. Such a method is not shared by different instances, though the
example here doesn't demonstrate that, since they would all be clone instance-methods.
The C and D examples provide a shared method to their instances.

Here are some ways to do what you might be wanting to do ;-)

 >>> class A:
 ...    def a_lengthy(self, params): return self, params
 ...
 >>> class B:
 ...    def __init__(self):
 ...        self.a_lengthy = A.a_lengthy.im_func.__get__(self, type(self))
 ...
 >>> class C:
 ...    a_lengthy = A.a_lengthy.im_func
 ...
 >>> class D:
 ...    a_lengthy = A.__dict__['a_lengthy']
 ...
 >>> a = A()
 >>> b = B()
 >>> c = C()
 >>> d = D()
 >>> a.a_lengthy('actual param')
 (<__main__.A instance at 0x02EF628C>, 'actual param')
 >>> b.a_lengthy('actual param')
 (<__main__.B instance at 0x02EF618C>, 'actual param')
 >>> c.a_lengthy('actual param')
 (<__main__.C instance at 0x02EF62EC>, 'actual param')
 >>> d.a_lengthy('actual param')
 (<__main__.D instance at 0x02EF16CC>, 'actual param')
 >>>
 >>> vars(a)
 {}
 >>> vars(b)
 {'a_lengthy': <bound method instance.a_lengthy of <__main__.B instance at 0x02EF618C>>}
 >>> vars(c)
 {}
 >>> vars(d)
 {}

Note that class B borrows the A method and makes an "instance-method" -- i.e.,
a bound method bound to the instance and set as an attribute of that instance
(which is why it shows up in vars(b)).

This mechanism could make customized instance-methods for different instances,
if you wanted to, since the class B is not modified by making variations.

A method is just a class variable whose value is a function, until it is
accessed as an attribute of either the class or an instance. What makes
it a method is the attribute-retrieval mechanism. So what you want to do
is possible, but A.a_lengthy_method is not the function, it is an unbound
method (because it was retrieved as an attribute of the class as opposed
to via an instance. For an ordinary method, you can get the function via
the im_func attribute, but if you want to borrow something trickier, you
may want to try the way class D does it.

For new-style classes, you will run across some differences.

Regards,
Bengt Richter



More information about the Python-list mailing list