pythonpython-3.xpython-objectpython-class

I want to call parent class method which is overridden in child class through child class object in Python


class abc():
    def xyz(self):
        print("Class abc")

class foo(abc):
    def xyz(self):
        print("class foo")

x = foo()

I want to call xyz() of the parent class, something like;

x.super().xyz()

Solution

  • With single inheritance like this it's easiest in my opinion to call the method through the class, and pass self explicitly:

    abc.xyz(x)
    

    Using super to be more generic this would become (though I cannot think of a good use case):

    super(type(x), x).xyz()
    

    Which returns a super object that can be thought of as the parent class but with the child as self.

    If you want something exactly like your syntax, just provide a super method for your class (your abc class, so everyone inheriting will have it):

    def super(self):
        return super(type(self), self)
    

    and now x.super().xyz() will work. It will break though if you make a class inheriting from foo, since you will only be able to go one level up (i.e. back to foo).

    There is no "through the object" way I know of to access hidden methods.

    Just for kicks, here is a more robust version allowing chaining super calls using a dedicated class keeping tracks of super calls:

    class Super:
        def __init__(self, obj, counter=0):
            self.obj = obj
            self.counter = counter
    
        def super(self):
            return Super(self.obj, self.counter+1)
    
        def __getattr__(self, att):
            return getattr(super(type(self.obj).mro()[self.counter], self.obj), att)
    
    
    class abc():
        def xyz(self):
            print("Class abc", type(self))
    
        def super(self):
            return Super(self)
    
    
    class foo(abc):
        def xyz(self):
            print("class foo")
    
    
    class buzz(foo):
        def xyz(self):
            print("class buzz")
    
    
    buzz().super().xyz()
    buzz().super().super().xyz()
    

    results in

    class foo
    Class abc