calling child class method from parent class file in python

54,242

Solution 1

Doing this would only make sense if A is an abstract base class, meaning that A is only meant to be used as a base for other classes, not instantiated directly. If that were the case, you would define methodB on class A, but leave it unimplemented:

class A(object):
    def methodA(self):
        print("in methodA")

    def methodB(self):
        raise NotImplementedError("Must override methodB")


from parent import A
class B(A):
    def methodB(self):
        print("am in methodB")

This isn't strictly necessary. If you don't declare methodB anywhere in A, and instantiate B, you'd still be able to call methodB from the body of methodA, but it's a bad practice; it's not clear where methodA is supposed to come from, or that child classes need to override it.

If you want to be more formal, you can use the Python abc module to declare A as an abstract base class.

from abc import ABC, abstractmethod

class A(ABC):

    def methodA(self):
        print("in methodA")

    @abstractmethod
    def methodB(self):
        raise NotImplementedError("Must override methodB")

Or if using Python 2.x:

from abc import ABCMeta, abstractmethod

class A(object):
 __metaclass__ = ABCMeta

    def methodA(self):
        print("in methodA")

    @abstractmethod
    def methodB(self):
        raise NotImplementedError("Must override methodB")

Using this will actually prevent you from instantiating A or any class that inherits from A without overriding methodB. For example, if B looked like this:

class B(A):
   pass

You'd get an error trying to instantiate it:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Can't instantiate abstract class B with abstract methods methodB

The same would happen if you tried instantiating A.

Solution 2

You can do something like this:

class A():
    def foo(self):
        self.testb()

class B(A):
    def testb(self):
        print('lol, it works')
b = B()
b.foo()

Which would return this of course:

lol, it works

Note, that in fact there is no call from parent, there is just call of function foo from instance of child class, this instance has inherited foo from parent, i.e. this is impossible:

a=A()
a.foo()

will produce: AttributeError: A instance has no attribute 'testb'

because

>>> dir(A)
['__doc__', '__module__', 'foo']
>>> dir(B)
['__doc__', '__module__', 'foo', 'testb']

What I've wanted to show that you can create instance of child class, and it will have all methods and parameters from both parent and it's own classes.

Solution 3

There are three approaches/ways to do this ! but I highly recommend to use the approach #3 because composition/decoupling has certain benefits in terms of design pattern. (GOF)

## approach 1 inheritance 
class A():
    def methodA(self):
        print("in methodA")
    def call_mehtodB(self):
        self.methodb()

class B(A):
    def methodb(self):
        print("am in methodb")

b=B()
b.call_mehtodB()


## approach 2 using abstract method still class highly coupled
from abc import ABC, abstractmethod
class A(ABC):
    def methodA(self):
        print("in methodA")
    @abstractmethod    
    def methodb(self):
       pass

class B(A):

    def methodb(self):
        print("am in methodb")

b=B()
b.methodb()

#approach 3 the recommended way ! Composition 

class A():
    def __init__(self, message):
        self.message=message

    def methodA(self):
        print(self.message)

class B():
    def __init__(self,messageB, messageA):
        self.message=messageB
        self.a=A(messageA)

    def methodb(self):
        print(self.message)

    def methodA(self):
        print(self.a.message)

b=B("am in methodb", "am in methodA")
b.methodb()
b.methodA()

Solution 4

You could use the function anywhere so long as it was attached to an object, which it appears to be from your sample. If you have a B object, then you can use its methodb() function from absolutely anywhere.

parent.py:

class A(object):
    def methoda(self):
        print("in methoda")

def aFoo(obj):
  obj.methodb()

child.py

from parent import A
class B(A):
    def methodb(self):
        print("am in methodb")

You can see how this works after you import:

>>> from parent import aFoo
>>> from child import B
>>> obj = B()
>>> aFoo(obj)
am in methodb

Granted, you will not be able to create a new B object from inside parent.py, but you will still be able to use its methods if it's passed in to a function in parent.py somehow.

Share:
54,242

Related videos on Youtube

Jagadeesh N M
Author by

Jagadeesh N M

I am having good experience building software tools like bug tracker, code review tracker, document review tracker. I glue tools to bring in automation to reduce human intervention. I have about decade of programming experience on c, perl, python and recently started golang.

Updated on February 19, 2022

Comments

  • Jagadeesh N M
    Jagadeesh N M over 2 years

    parent.py:

    class A(object):
        def methodA(self):
            print("in methodA")
    

    child.py:

    from parent import A
    class B(A):
        def methodb(self):
            print("am in methodb")
    

    Is there anyway to call methodb() in parent.py?

    • roippi
      roippi almost 10 years
      If you need to, that is a pretty significant code smell.
    • Jagadeesh N M
      Jagadeesh N M almost 10 years
      May be I am doing it wrong but looking for other smarter approach.
    • kratenko
      kratenko almost 10 years
      @JagadeeshNM It's hard to say what you might be doing wrong and how to be smarter, because it is not obvious what you are actually trying to achieve by doing this. Sounds a bit like your problem comes from an unhappy approach in your broader program design...
  • naught101
    naught101 about 5 years
    Why set __metaclass__ explicitly, and not just use ABC as a base class in the definition?
  • Olivier Pons
    Olivier Pons about 4 years
    In your 3rd suggestion, how do you d a=A() and a.methodb() (which is what the original question is, if i'm not wrong)
  • dano
    dano over 2 years
    @naught101 When I wrote this answer, I think that using __metaclass__ was the only way to do it (and is still the only way on Python 2.x). I agree that if you're using Python 3 these days using ABC as the base class is the correct way. I've updated my answer accordingly.