Pythonオブジェクト向けマルチ継承MRO

4912 ワード

Pythonオブジェクト向けマルチ継承MRO
レビュー-クラス継承
サブクラスの継承についてすなわち、子クラスは親クラスのすべてのメソッドおよび属性を継承することができ、子クラスが新しい機能を追加するか、親クラスを変更する方法は、子クラスでoverwriteを私的に書き換えることができる.振り返ってみればいいだろうが、ここではあまりにも基礎的な問題について検討したくない.
class A:
    def __init__(self):
        self.a = 10
        self.b = 20

    @staticmethod
    def say_hello():
        print("hello, world!")

子クラスの初期化では、親クラスの初期化方法を手動で呼び出す必要があります.構文は**親クラス名._です.init__(self, ...)**
class B(A):
    def __init__(self, c, d):
        """    __init__,    d, e  """
        self.c = c
        self.d = d
        A.__init__(self)
        
        
        
if __name__ == '__main__':
    b = B(4, 5)
    print(b.a)
    print(b.d)

    # output
    10
    5

もちろんsuperキーワードで
class B(A):
    def __init__(self, c, d):
        """    __init__,    d, e  """
        self.c = c
        self.d = d
        super().__init__()

マルチ継承-Bug
ここで主に1つのプレゼンテーションをして、多く受け継ぐと現れる問題、実はバグではありませんて、原理は私もよく推敲したことがありませんて、先に現れてみましょう.
class   :
    def __init__(self, name):
        self.name = name
        print("i am you father...")


class   (  ):
    def __init__(self, name, age):
        self.age = age
          .__init__(self, name)
        print(" i am eldest son")

class   (  ):
    def __init__(self, name, gender):
        self.gender = gender
          .__init__(self, name)
        print("i am the little son")

class   (  ,   ):
    """    """
    def __init__(self, name, age, gender):
          .__init__(self, name, age)
          .__init__(self, name, gender)
        print("i am the sweet heart")


if __name__ == '__main__':

    king =   ("   ", 23, "F")
i am you father...
i am eldest son
    
i am you father...  #        ???

i am the little son
i am the sweet heart

寝槽父は2回実行されましたが、メモリの無駄な感じがしますね.うん.ちょっと緊張して...
なぜ2回呼び出した親が現れるのでしょうか.あるいはどのようにして呼び出しを一度だけすればいいのでしょうか.上のコードを分析します
  .__init__(self, name, age) --> class   (  ) --> class    -> print("father...")
  .__init__(self, name, gender) --> class   (  ) --> class    -> print("father...")

そのため、2回呼び出されても問題はありませんが、メモリの無駄、スペースの繰り返しのため、新しい最適化の問題をもたらします.
より一般的には、マルチ継承の場合、親の属性が複数回実行する場合があり、ここでは単純なcaseにすぎず、非常に複雑な結果であると、非常に多くのメモリと繰り返し呼び出しが浪費される.
マルチ継承MRO
MRO-導入
MROはPyhtonが上記のような問題を解決するために用いるものであり、空間を繰り返し開く問題が生じる.解決策は、複雑な構造上のすべてのクラスを1つの線形順序(線形テーブル)にマッピングすることであり、この順序がMRO順序である.
MROテーブルは、事前に呼び出しておき、テーブルの順番に呼び出し、右から左へ
print(  .__mro__)

# output

(, , , , )

このリニアテーブルは、私が実行する観点から見ると、スタックで、親がスタックの底にいて、王子様がスタックの頂上にいて(Top)、検索の順序、兄弟たち、目を凝らして見ると、この層、1層目の検索、...これが木の広さ優先アルゴリズムだと思います.
MRO - super
政府はすでにこの問題を解決しており、方法は内蔵方法super()である.
super()の方法はPython 2では違いますよ、Python 3はもっと簡潔で、直接親の部品を持っています
super()-マルチ継承
class   :
    def __init__(self, name):
        self.name = name
        print("i am you father...")

# tips:        ,       *args, **kwargs  
class   (  ):
    def __init__(self, name, age, *args): # *args    gender .
        self.age = age
        super().__init__(name, *args)
        print(" i am eldest son")


class   (  ):
    def __init__(self, name, gender):
        self.gender = gender
        super().__init__(name)
        print("i am the little son")


class   (  ,   ):
    """    """

    def __init__(self, name, age, gender):
        super().__init__(name,  age, gender)
        print("i am the sweet heart")


if __name__ == '__main__':
    king =   ("   ", 23, "F")
    print(  .__mro__)
i am you father...
i am the little son
i am eldest son
i am the sweet heart

(, , , , )

小結
  • マルチ継承は、メモリ領域
  • を浪費する繰り返し呼び出しの問題を生じる.
  • MROシーケンスはPythonがクラスを1つの線形テーブルにマッピングして呼び出すので、秩序正しく、繰り返し呼び出しを避けることができ、検索アルゴリズムの目視は広さ優先
  • である.
  • superの理解と用法、注意点は伝参の数の問題で、分からないで、すべて共通の形式(*args、**kwargs)
  • であることができます
    それともsuper()について少し詳しくて、単一継承の中で、super()です.xxxと父の名前...両者は同じ効果ですが、マルチ継承ではsuper()が親メソッドを一度だけ実行するようになり、従来のメソッドでは、上記のような「ダイヤモンド呼び出しの問題」**super()を使用する場合は、パラメータをすべて渡す必要があります.tips、後に*args**kwargs**を付けます.
    最初の例から見ると、単一継承の時、super()メソッドは親メソッドに必要なパラメータしか伝達できないし、args kwargsもできないようで、いつもこれらの設計を感じて、変なことをして、すべてdebugが長いです.マルチ継承では、書き換えや継承が一般的に使われています.init__()**、ここではsuper()の利点が現れ、1行のコードだけで親クラスを実行することができます.うん、たぶん、これがsuper()がすべてのパラメータを渡すことを要求している理由でしょう.
    类の方式を使うことについて、やはりsuper()を使って、私は感じて、私のふだん书いた脚本、基本的にすべて使って継承することができなくてははははははは、本当に少し気まずいですが、全身の技能を感じて、いつも私にいくつかをさせて、雑用の仕事...知己は探しにくくて、やっと退屈でブログを书いて、ブログを写して、下ネタを写して、コードを写します....