Skipping a superclass

2009-08-02 Thread Steven D'Aprano
I have a series of subclasses like this:

class A(object):
def method(self, *args):
print Lots of work gets done here in the base class

class B(A):
def method(self, *args):
print A little bit of work gets done in B
super(B, self).method(*args)

class C(B):
def method(self, *args):
print A little bit of work gets done in C
super(C, self).method(*args)


However, the work done in C.method() makes the work done in B.method() 
obsolete: I want one to run, or the other, but not both. C does need to 
inherit from B, for the sake of the other methods, so I want C.method() 
*only* to skip B while still inheriting from A. (All other methods have 
to inherit from B as normal.)

So what I have done is change the call to super in C to super(B, self) 
instead of super(C, self). It seems to work, but is this safe to do? Or 
are there strange side-effects I haven't seen yet?



-- 
Steven
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Skipping a superclass

2009-08-02 Thread Chris Rebert
On Sun, Aug 2, 2009 at 5:36 AM, Steven
D'Apranost...@remove-this-cybersource.com.au wrote:
 I have a series of subclasses like this:

 class A(object):
    def method(self, *args):
        print Lots of work gets done here in the base class

 class B(A):
    def method(self, *args):
        print A little bit of work gets done in B
        super(B, self).method(*args)

 class C(B):
    def method(self, *args):
        print A little bit of work gets done in C
        super(C, self).method(*args)


 However, the work done in C.method() makes the work done in B.method()
 obsolete: I want one to run, or the other, but not both. C does need to
 inherit from B, for the sake of the other methods, so I want C.method()
 *only* to skip B while still inheriting from A. (All other methods have
 to inherit from B as normal.)

 So what I have done is change the call to super in C to super(B, self)
 instead of super(C, self). It seems to work, but is this safe to do? Or
 are there strange side-effects I haven't seen yet?

Barring some true weirdness in super(), I don't /think/ so. It
obviously works fine in the single-inheritance case, and (after some
brute-force testing) the only permitted multiple inheritances
involving C and (A or B) always have C ahead of B in the MRO (method
resolution order).

The fact that you're wanting to bypass a superclass method might
suggest however, that your hierarchy could be structured better. Have
you considered moving B.method() into another, new class (e.g. newB)
which subclasses B? Then C can inherit from B without inheriting the
unwanted method, while B's functionality still exists, just under a
new name (newB).

Cheers,
Chris
-- 
http://blog.rebertia.com
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Skipping a superclass

2009-08-02 Thread Miles Kaufmann

On Aug 2, 2009, at 5:36 AM, Steven D'Aprano wrote:

I have a series of subclasses like this:

class A(object):
   def method(self, *args):
   print Lots of work gets done here in the base class

class B(A):
   def method(self, *args):
   print A little bit of work gets done in B
   super(B, self).method(*args)

class C(B):
   def method(self, *args):
   print A little bit of work gets done in C
   super(C, self).method(*args)


However, the work done in C.method() makes the work done in B.method()
obsolete: I want one to run, or the other, but not both. C does need  
to
inherit from B, for the sake of the other methods, so I want  
C.method()
*only* to skip B while still inheriting from A. (All other methods  
have

to inherit from B as normal.)


This might not be applicable to the larger problem you're trying to  
solve, but for this sample, I would write it as:


class A(object):
def method(self, *args):
self._method(*args)
print Lots of work gets done here in the base class
def _method(self, *args):
pass # or perhaps raise NotImplemented

class B(A):
def _method(self, *args):
print A little bit of work gets done in B

class C(B):
def _method(self, *args):
print A little bit of work gets done in C


So what I have done is change the call to super in C to super(B, self)
instead of super(C, self). It seems to work, but is this safe to do?  
Or

are there strange side-effects I haven't seen yet?


In a diamond-inheritance situation, you may end up skipping methods  
besides just B.method().


-Miles

--
http://mail.python.org/mailman/listinfo/python-list