Pythonマルチ継承とsuper使用の詳細


Pythonはマルチ継承をサポートしていますが、pythonがサポートするマルチ継承も限られています.
0.問題の提出
  • 異なる親クラスに同じ名前のメソッドが存在する場合、子クラスオブジェクトはメソッドを呼び出すときに、どの親クラスのメソッドを呼び出すのでしょうか.

  • PythonのMRO-メソッド検索順
  • Pythonには、クラスに対する組み込み属性__mro__が提供する、メソッド検索順序
  • を表示することができる.
  • MROはmethod resolution orderであり、主にマルチ継承時の判断方法、属性の呼び出し経路
  • に用いる.
    print(C.__mro__)  #C        
    

    出力結果
    (, , , )
    
  • 探索方法の場合、__mro__の出力結果に従って左から右の順に探索する
  • である.
  • 現在のクラスでメソッドが見つかった場合は、
  • を検索せずに直接実行します.
  • 見つからない場合は、次のクラスに対応するメソッドがあるかどうかを検索し、見つかったら直接実行し、
  • を検索しません.
  • 最後のクラスが見つかった場合、まだ方法が見つからない場合、プログラムエラー
  • 1.マルチ継承の使用
    #1.   :       
    
    class Human:
        def __init__(self, sex):
            self.sex = sex
    
        def p(self):
            print("  Human   ")
    
    
    class Person:
        def __init__(self, name):
            self.name = name
    
        def p(self):
            print("  Person   ")
    
        def person(self):
            print("   person     ")
    
    
    class Teacher(Person):
        def __init__(self, name, age):
            super().__init__(name)
            self.age = age
    
    
    class Student(Human, Person):
        def __init__(self, name, sex, grade):
        #                   .__init__  。     super,     ,      
           Human.__init__(self,sex)
           Person.__init__(self,name)
           self.grade = grade
    
    
    class Son(Human, Teacher):
        def __init__(self, sex, name, age, fan):
            Human.__init__(self, sex)
            Teacher.__init__(self, name, age)
            self.fan = fan
    
    
    # ------     -------------
    stu = Student("tom", "male", 88)
    print(stu.name,stu.sex,stu.grade)
    stu.p()  #     Human Person    P()   ,               Human   
    
    
    son1 = Son("jerry", "female", 18, "  ")
    son1.person()  #             。
    son1.p()  #               ,        。
    =====================================================================================
    tom male 88
      Human   
       person     
      Human   

    まとめ:1.カッコで親の順序を継承することに注意してください.親に同じメソッド名があり、子の使用時に指定されていない場合は、pythonが左から右に検索します.つまり、メソッドが子に見つからない場合は、左から右に検索して親にメソッドが含まれているかどうかを検索します.
               2.多層親の継承をサポートし、子は親のすべての属性とメソッドを継承します.親の親のすべての属性とメソッドが含まれます.
    2.マルチ継承の使用上の注意事項
    #1.               
    class Human:
        def __init__(self,sex):
            self.sex = sex
        def p(self):
            print("  Human   ")
        def str1(self):
            print("this si"+str(self.sex))
    
    class Person:
        def __init__(self,name):
            self.name = name
        def p(self):
            print("  Person   ")
        def person(self):
            print("   person     ")
    
        def str2(self):
            print( "this is:" + str(self.name))
    
    class Student(Human,Person): #             ,                    ,     
        def prin(self):
            print("student")
    #------     -------------
    #stu1=Studnent(" ","tom")  。
    stu = Student("sex") #      Huma     。
    stu.p()
    stu.str1() 
    #stu.str2()  ,    human person           ,             Human     
    ====================================================================================
      Human   
    this sisex

    まとめ:子が複数の親から派生し、子が独自のコンストラクション関数を持たない場合、
    (1)順序に従って継承し、どの親が一番前にいて自分の構造関数を持っているか、その構造関数を継承する.
    (2)最初の親にコンストラクション関数がない場合は,2番目のコンストラクション関数を継承し,2番目にない場合は,後で探して,このようにする.
    3.マルチ継承時にsuperを使用して親属性メソッドを呼び出す注意事項
    3.1 super呼び出し親メソッドを使用せず、親クラス名を使用する.メソッド名の形式.
    class Parent(object):
        def __init__(self, name):
            print('parent init     ')
            self.name = name
            print('parent init     ')
    
    class Son1(Parent):
        def __init__(self, name, age):
            print('Son1 init     ')
            self.age = age
            Parent.__init__(self, name) #       .           __init__  
            print('Son1 init     ')
    
    class Son2(Parent):
        def __init__(self, name, gender):
            print('Son2 init     ')
            self.gender = gender
            Parent.__init__(self, name) #
            print('Son2 init     ')
    
    class Grandson(Son1, Son2):
        def __init__(self, name, age, gender):
            print('Grandson init     ')
            Son1.__init__(self, name, age)  #             
            Son2.__init__(self, name, gender)
            print('Grandson init     ')
    
    gs = Grandson('grandson', 12, ' ') 
    print('  :', gs.name)
    print('  :', gs.age)
    print('  :', gs.gender)
    
    '''      :
    Grandson init     
    Son1 init     
    parent init     
    parent init     
    Son1 init     
    Son2 init     
    parent init     
    parent init     
    Son2 init     
    Grandson init     
      : grandson
      : 12
      :  
    '''

    注意:上のコードでは、サブクラスで親クラス名で呼び出されるとparentが2回実行されます.
    3.2 superを使用して親クラスのメソッドを呼び出し、分析プログラムの実行順序に注意します.
    class Parent(object):
        def __init__(self, name, *args, **kwargs):  #         ,       ,    
            print('parent init     ')
            self.name = name
            print('parent init     ')
    
    class Son1(Parent):
        def __init__(self, name, age, *args, **kwargs):  #         ,       ,    
            print('Son1 init     ')
            self.age = age
            super().__init__(name, *args, **kwargs)  #         ,       ,    
            print('Son1 init     ')
    
    class Son2(Parent):
        def __init__(self, name, gender, *args, **kwargs):  #         ,       ,    
            print('Son2 init     ')
            self.gender = gender
            super().__init__(name, *args, **kwargs)  #         ,       ,    
            print('Son2 init     ')
    
    class Grandson(Son1, Son2):
        def __init__(self, name, age, gender):
            print('Grandson init     ')
            #     ,       .__init__  ,           
            #  super     ,          ,                   
            # super(Grandson, self).__init__(name, age, gender)         
            super().__init__(name, age, gender)
            print('Grandson init     ')
    
    print(Grandson.__mro__) #    
    
    gs = Grandson('grandson', 12, ' ')
    
    print('  :', gs.name)
    print('  :', gs.age)
    print('  :', gs.gender)
    
    '''    :
    (, , , , )
    Grandson init     
    Son1 init     
    Son2 init     
    parent init     
    parent init     
    Son2 init     
    Son1 init     
    Grandson init     
      : grandson
      : 12
      :  
    '''

    注:上記のモジュールでは、サブクラスでsuperによって親メソッドが呼び出されるとparentが1回実行されます.
    super呼び出しプロシージャ:上のgsが初期化されるとgrandsonでのinitメソッドが実行され、その中のinitにはsuper呼び出しがあり、superが実行されるたびに_mro__メソッドメタグループ内の検索順序.だから先にson 1のinitメソッドを呼び出して、son 1の中でまたsuper呼び出しがあって、この時__によってmro__テーブルはson 2のinitを呼び出し、son 2にsuper呼び出しがあり、これはmroテーブルに基づいてparentのinitを呼び出し、objectのinitを呼び出すまで呼び出す.したがって、上記の印刷結果は、実行プロセスを注意深く分析する必要があります.
    絶叫のヒント:
  •  super().__init__クラス名に対して._init__,単一継承における用法はほぼ無差
  • しかし、マルチ継承に違いがあり、superメソッドは親クラスごとのメソッドが1回しか実行されないことを保証することができ、クラス名を使用するメソッドはメソッドが複数回実行されることを招き、具体的には前の出力結果
  • を参照する.
  • マルチ継承の場合、superメソッドを使用して親への伝達パラメータは、pythonにおけるsuperのアルゴリズムによるものであるべきであり、パラメータをすべて伝達しなければならない.そうしないと
  • とエラーが発生する.
  • 単一継承の場合、superメソッドを使用すると、すべてを渡すことができず、親メソッドに必要なパラメータのみを伝えることができます.そうしないと、
  • とエラーが発生します.
  • マルチ継承の場合、クラス名の使用に対して._init__メソッドは、各親をすべて書き、superメソッドを使用して、一言書くだけですべての親のメソッドを実行します.これも、なぜ多く継承するにはすべてのパラメータを必要とする理由の1つです.
  • 3.3単一継承superを使用して親メソッドを呼び出す
    class Parent(object):
        def __init__(self, name):
            print('parent init     ')
            self.name = name
            print('parent init     ')
    
    class Son1(Parent):
        def __init__(self, name, age):
            print('Son1 init     ')
            self.age = age
            super().__init__(name)  #            
            print('Son1 init     ')
    
    class Grandson(Son1):
        def __init__(self, name, age, gender):
            print('Grandson init     ')
            super().__init__(name, age)  #            
            print('Grandson init     ')
    
    gs = Grandson('grandson', 12, ' ')
    print('  :', gs.name)
    print('  :', gs.age)

    統一声明:オリジナルブログの内容については、一部の内容がインターネットから参照されている可能性があります.オリジナルリンクがあれば参照を宣言します.オリジナルリンクが見つからない場合は、権利侵害がある場合は削除に連絡してください.ブログの転載については、オリジナルリンクがあれば声明します.オリジナルリンクが見つからない場合は、権利侵害がある場合は削除に連絡してください.