web-dev-qa-db-ja.com

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

_parent.py_でmethodb()を呼び出す方法はありますか?

18
Jagadeesh N M

これを行うことは、Aが抽象基本クラスである場合にのみ意味があります。つまり、Aは、直接インスタンス化されず、他のクラスの基本としてのみ使用されることを意味します。その場合は、クラスAでmethodBを定義しますが、実装しないでください。

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をインスタンス化しようとした場合も同じことが起こります。

25
dano

あなたはこのようなことをすることができます:

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

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

これはもちろんこれを返します:

lol, it works

実際には、親からの呼び出しはなく、子クラスのインスタンスからの関数fooの呼び出しのみがあることに注意してください。このインスタンスは、親からfooを継承しています。つまり、これは不可能です。

a=A()
a.foo()

生成されます:AttributeError: A instance has no attribute 'testb'

なぜなら

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

私が見せたかったのは、子クラスのインスタンスを作成できることです。これには、親クラスと自身のクラスの両方からのすべてのメソッドとパラメーターが含まれます。

8
Alexey

関数はどこからでも使用できますオブジェクトにアタッチされている限り。これはサンプルからのようです。 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

確かに、parent.py内から新しいBオブジェクトを作成することはできませんが、何らかの方法でparent.pyの関数に渡された場合は、そのメソッドを引き続き使用できます。 。

2
TheSoundDefense

これを行うには3つの方法があります。ただし、構成/デカップリングには設計パターンの点で特定の利点があるため、アプローチ#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()
2
grepit