22

Pythonチュートリアルでは、「Pythonは限定された形式の多重継承をサポートしている」と言われています。

制限は何ですか?

4

2 に答える 2

12

Pythonチュートリアルの作成者がどのような制限を参照していたかはわかりませんが、Pythonでメソッド/属性ルックアップを実装する方法(「メソッド解決順序」またはMRO)に部分的に関係していると思います。PythonはC3スーパークラス線形化メカニズムを使用します。これは、「菱形継承問題」と呼ばれるものに対処するためのものです。

クラス階層に多重継承を導入すると、特定のクラスには、継承元の潜在的なクラスが1つもなくなり、一部のクラスから継承することを期待するクラスであっても、「MROの次のクラス」のみが含まれます。特にクラス。

たとえば、、、、、およびの場合class A(object)、クラスclass B(A)のMROはです。クラスBは、おそらくAの子孫であると考えて作成された可能性があり、それ自体を呼び出すと、Aのメソッドを取得します。しかし、これはもはや真実ではありません。Bがを呼び出すと、代わりにCのメソッドが存在する場合はそれを取得します。class C(A)class D(B, C)DD->B->C->Asuper()super()

オーバーライドされたメソッドでメソッドシグネチャを変更すると、これが問題になる可能性があります。クラスBは、superを呼び出すときにクラスAからのメソッドのシグネチャを期待しますが、代わりにCからメソッドを取得します。このメソッドは、そのシグネチャを持たない可能性があります(クラスBの観点からは、目的の動作を実装する場合としない場合があります)。

class A(object):
    def __init__(self, foo):
        print "A!"

class B(A):
    def __init__(self, foo, bar):
        print "B!"
        super(B, self).__init__(foo)

class C(A):
    def __init__(self, foo, baaz):
        print "C!"
        super(C, self).__init__(foo)

class D(B, C):
    def __init__(self, foo, bar):
        print "D!"
        super(D, self).__init__(foo, bar)

print D.mro()
D("foo", "bar")

このコードサンプルでは、​​クラスBとCはAを適度に拡張し、__init__シグニチャを変更していますが、期待されるスーパークラスシグニチャを正しく呼び出しています。しかし、Dをそのようにすると、Bの効果的な「スーパークラス」はAではなくCになります。スーパーと呼ばれると、物事は爆発します。

[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <type 'object'>]
D!
B!
Traceback (most recent call last):
  File "/tmp/multi_inherit.py", line 22, in <module>
    D("foo", "bar")
  File "/tmp/multi_inherit.py", line 19, in __init__
    super(D, self).__init__(foo, bar)
  File "/tmp/multi_inherit.py", line 9, in __init__
    super(B, self).__init__(foo)
TypeError: __init__() takes exactly 3 arguments (2 given)

これと同じ種類のことが他のメソッドでも発生する可能性があり(呼び出した場合super())、「ひし形」はクラス階層のルートにのみ表示される必要はありません。

于 2012-05-20T16:21:13.790 に答える
5

@Matt Andersonの回答とは別に、制限は実際には古いスタイルのクラスにあると思います(Python 2.6のチュートリアルではまだ対処されています)。

Python 3 チュートリアルでは、テキストは次のようになりました: Python は多重継承の形式もサポートしています

于 2012-05-21T12:44:51.213 に答える