views:

9133

answers:

4

Stackers,

I apologize for this question in advance. It must be a FAQ, but I don't seem to be able to find the answer.

When creating a simple object hierarchy in python, I'd like to be able to invoke methods of the parent class from a derived class. In Perl and Java, there is a keyword for this (super). In Perl, I might do this:

package Foo;

sub frotz() {
    return "Bamf";
}

package Bar;
@ISA = qw(Foo);

sub frotz() {
   my $str = SUPER::frotz();
   return uc($str);
}

In python, it appears that I have to name the parent class explicitly from the child. In the example above, I'd have to do something like Foo::frotz().

This doesn't seem right, since this behavior makes it hard to make deep hierarchies. If children need to know what class defined an inherited method, then all sorts of information pain is created.

Is this an actual limitation in python, a gap in my understanding or both?

Thanks,

--Joe

+17  A: 

Yes, but only with new-style classes. Use the super() function:

class Foo(Bar):
    def baz(self, arg):
        return super(Foo, self).baz(arg)
Adam Rosenfield
Can you not also do "return Bar.baz(self, arg)"? If so, which would be better?
Chris Cameron
Yes, you can, but the OP was asking how to do it without explicitly naming the superclass at the call site (Bar, in this case).
Adam Rosenfield
-1: forgot to mention `class Foo( object ): ` is essential for making this work.
S.Lott
Well, Adam does note it's restricted to "new-style classes", which is a link that has as its first line, "Any class which inherits from object."
John Fouhy
@John Fouhy: All true, but also implicit. An extra line or two of what "new-sty;e" means in actual code can be helpful.
S.Lott
Thank you. I don't have a good handle on the two Python object models. I'll get my read-on. Thank you all.
jjohn
super() is weird with multiple inheritance. It calls to the "next" class. That might be the parent class, or might be some completely unrelated class which appears elsewhere in the hierarchy.
Steve Jessop
+2  A: 

Python also has super as well:

super(type[, object-or-type])

Return a proxy object that delegates method calls to a parent or sibling class of type. This is useful for accessing inherited methods that have been overridden in a class. The search order is same as that used by getattr() except that the type itself is skipped.

Example:

class A(object):
    def foo(self):
        print "foo"

class B(A):
    def foo(self):
        super(B, self).foo()

myB = B()
myB.foo()
Jay
A: 

There's a super() in Python too. It's a bit wonky, because of Python's old- and new-style classes, but is quite commonly used e.g. in constructors:

class Foo(Bar):
    def __init__(self):
        super(Foo, self).__init__()
        self.baz = 5
lawrence
I think you mean: 'super(Foo, self).__init__()'
John Fouhy
oops... indeed i did
lawrence
+1  A: 

ImmediateParentClass.frotz(self) will be just fine, whether the immediate parent class defined frotz itself or inherited it. super is only needed for proper support of multiple inheritance (and then it only works if every class uses it properly). In general, AnyClass.whatever is going to look up 'whatever' in AnyClass's ancestors if AnyClass doesn't define/override it, and this holds true for "child class calling parent's method" as for any other occurrence!

Alex Martelli