Вызов метода дочернего класса из файла родительского класса в python

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")

Есть ли methodb() вызвать methodb() в parent.py?

Ответ 1

Выполнение этого имеет смысл только в том случае, если A является абстрактным базовым классом, что означает, что A предназначен только для использования в качестве базы для других классов, а не для непосредственного создания. Если бы это было так, вы бы определили methodB в классе A, но не допустили его:

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")

Это не обязательно. Если вы не объявляете methodB нигде в A и не создаете экземпляр B, вы все равно сможете вызвать methodB из тела methodA, но это плохая практика; неясно, откуда предполагается methodA, или что дочерние классы должны переопределить его.

Если вы хотите быть более формальным, вы можете использовать модуль Python abc для объявления A как абстрактного базового класса.

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")

Использование этого фактически не позволит вам создавать экземпляр A или любой класс, который наследует от A без переопределения methodB. Например, если B выглядел так:

class B(A):
   pass

У вас возникнет ошибка при попытке его создания:

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

То же самое произойдет, если вы попытаетесь создать экземпляр A.

Ответ 2

Вы можете сделать что-то вроде этого:

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

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

Обратите внимание, что на самом деле нет вызова от родителя, есть только вызов функции foo из экземпляра дочернего класса, этот экземпляр унаследовал foo от родителя, т.е. это невозможно:

a=A()
a.foo()

будет производить:   AttributeError: A instance has no attribute 'testb'

потому что

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

Что я хотел показать, что вы можете создать экземпляр дочернего класса, и он будет иметь все методы и параметры как из родителя, так и из его собственных классов.

Ответ 3

Вы можете использовать эту функцию в любом месте, пока она была прикреплена к объекту, который, по-видимому, относится к вашему образцу. Если у вас есть объект B, вы можете использовать его функцию methodb() из абсолютно где угодно.

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")

Вы можете увидеть, как это работает после импорта:

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

Конечно, вы не сможете создать новый объект B изнутри parent.py, но вы все равно сможете использовать его методы, если он каким-то образом перешел к функции в parent.py.

Ответ 4

Есть три подхода/способа сделать это! но я настоятельно рекомендую использовать подход № 3, потому что композиция/разделение имеет определенные преимущества с точки зрения шаблона проектирования. (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()

Ответ 5

Нет, вы не должны пытаться вызывать метод в родительском классе, когда он определен в дочернем классе. Хотя вы можете использовать обходной путь, чтобы позволить это, это плохая практика. Подумайте, нужно ли всем детям использовать этот метод и перенести его в родительский класс. Если метод нужен не всем детям, оставьте его в классе детей.