ホームページ  >  記事  >  バックエンド開発  >  Pythonのsuper()メソッドの詳しい解説

Pythonのsuper()メソッドの詳しい解説

爱喝马黛茶的安东尼
爱喝马黛茶的安东尼転載
2019-08-22 17:27:132375ブラウズ

Pythonのsuper()メソッドの詳しい解説

#1. 親クラスのメソッドを個別に呼び出す

要件: クラスを作成し、サブクラスを作成します。そして、サブクラスを使用して親クラスのメソッド 1 を呼び出します。

方法 1 を使用して印刷します: 太った上司、ビンロウを詰めに来てください。

次に、最初にファット ボスの親クラスを作成して実行します。

class FatFather(object):
    def __init__(self, name):
        print('FatFather的init开始被调用')
        self.name = name
        print('FatFather的name是%s' % self.name)
        print('FatFather的init调用结束')
def main():
    ff = FatFather("胖子老板的父亲")

次のようにファット ボスの親クラスのコンストラクター init を実行します。

if __name__ == "__main__":
    main()
FatFather的init开始被调用
FatFather的name是胖子老板的父亲
FatFather的init调用结束

わかりました。上記のクラスを継承するサブクラス、つまり Fat Boss クラスを作成しましょう。

# 胖子老板的父类
class FatFather(object):
    def __init__(self, name):
        print('FatFather的init开始被调用')
        self.name = name
        print('调用FatFather类的name是%s' % self.name)
        print('FatFather的init调用结束')
# 胖子老板类 继承 FatFather 类
class FatBoss(FatFather):
    def __init__(self, name, hobby):
        print('胖子老板的类被调用啦!')
        self.hobby = hobby
        FatFather.__init__(self, name)  # 直接调用父类的构造方法
        print("%s 的爱好是 %s" % (name, self.hobby))
def main():
    #ff = FatFather("胖子老板的父亲")
    fatboss = FatBoss("胖子老板", "打斗地主")

上記のコードでは、FatFather.init(self,name) を使用して親クラスのメソッドを直接呼び出しています。

実行結果は以下の通りです:

if __name__ == "__main__":
    main()
胖子老板的类被调用啦!
FatFather的init开始被调用
调用FatFather类的name是胖子老板
FatFather的init调用结束
胖子老板 的爱好是 打斗地主

2. super() メソッドの基本概念

FatFather を直接使用する方法の他に.init(self,name) 、および super() メソッドを使用して呼び出すこともできます。

次に、まず super() メソッドの説明と構文を読んで、super() メソッドの使用法を理解する必要があります。

2.1 説明

super() 関数は、親クラス(スーパークラス)を呼び出すためのメソッドです。

super は多重継承の問題を解決するために使用されます。単一継承を使用する場合は、クラス名を指定して親クラスのメソッドを直接呼び出すことは問題ありません。ただし、多重継承を使用すると、検索順序 (MRO) が関係します。 )および繰り返しの電話(ダイヤモンドの相続)およびその他の問題。

MRO はクラスのメソッド解析順序表で、実際には親クラスのメソッドを継承するときの順序表です。

関連する推奨事項: 「

Python ビデオ チュートリアル

2.2 構文

次は、super() の構文です。 Method:

super(type[, object-or-type])

Parameters

type -- class

object-or-type -- クラス、通常は self

Python3.x および Python2 のいずれか.x 違いは次のとおりです。Python 3 では、super(Class, self).xxx の代わりに super().xxx を直接使用できます。

Python3.x 例:

class A:
    pass
class B(A):
    def add(self, x):
        super().add(x)

Python2.x 例:

class A(object):   # Python2.x 记得继承 object
    pass
class B(A):
    def add(self, x):
        super(B, self).add(x)

2.3 単一継承では super() を使用します

super() メソッドを使用して、親クラスを継承するファット ボスの init 構築メソッドを書き換えます

# 胖子老板的父类
class FatFather(object):
    def __init__(self, name):
        print('FatFather的init开始被调用')
        self.name = name
        print('调用FatFather类的name是%s' % self.name)
        print('FatFather的init调用结束')
# 胖子老板类 继承 FatFather 类
class FatBoss(FatFather):
    def __init__(self, name, hobby):
        print('胖子老板的类被调用啦!')
        self.hobby = hobby
        #FatFather.__init__(self,name)   # 直接调用父类的构造方法
        super().__init__(name)
        print("%s 的爱好是 %s" % (name, self.hobby))
def main():
    #ff = FatFather("胖子老板的父亲")
    fatboss = FatBoss("胖子老板", "打斗地主")

上から使用 スーパーメソッドを使用する場合は、単一継承なので直接使用できます。

次のように実行します:

if __name__ == "__main__":
    main()
胖子老板的类被调用啦!
FatFather的init开始被调用
调用FatFather类的name是胖子老板
FatFather的init调用结束
胖子老板 的爱好是 打斗地主

では、なぜ単一継承を直接使用できると言われるのでしょうか? super() メソッドに多重継承がある場合、MRO (親クラスのメソッドを継承するときのシーケンス テーブル) の呼び出し順序の問題が発生するためです。

これを以下に印刷して、単一継承の MRO シーケンス (FatBoss.mro) を確認できます。

# 胖子老板的父类
class FatFather(object):
    def __init__(self, name):
        print('FatFather的init开始被调用')
        self.name = name
        print('调用FatFather类的name是%s' % self.name)
        print('FatFather的init调用结束')
# 胖子老板类 继承 FatFather 类
class FatBoss(FatFather):
    def __init__(self, name, hobby):
        print('胖子老板的类被调用啦!')
        self.hobby = hobby
        #FatFather.__init__(self,name)   # 直接调用父类的构造方法
        super().__init__(name)
        print("%s 的爱好是 %s" % (name, self.hobby))
def main():
    print("打印FatBoss类的MRO")
    print(FatBoss.__mro__)
    print()
    print("=========== 下面按照 MRO 顺序执行super方法 =============")
    fatboss = FatBoss("胖子老板", "打斗地主")

上記のコードは、FatBoss.mro を使用して、Python パーサーの C3 アルゴリズムによって計算された FatBoss クラスの継承呼び出しシーケンスを出力します。

次のように実行します:

if __name__ == "__main__":
    main()
打印FatBoss类的MRO
(<class &#39;__main__.FatBoss&#39;>, <class &#39;__main__.FatFather&#39;>, <class &#39;object&#39;>)
=========== 下面按照 MRO 顺序执行super方法 =============
胖子老板的类被调用啦!
FatFather的init开始被调用
调用FatFather类的name是胖子老板
FatFather的init调用结束
胖子老板 的爱好是 打斗地主

上記の結果から (819fb8321e79eba8a7ae9f208b30d85a, 19021db2abd6a327a019e93aad66dcb4,

では、多重継承がある場合にはどのような問題があるのでしょうか?

2.4 super()を使用した多重継承

太った上司の娘用に別のクラスを作成し、太った上司の妻用にクラスを作成するとします。同時に、娘は両方のカテゴリ(太った上司のカテゴリ、太った上司の妻のカテゴリ)を同時に継承する必要があります。

デブ上司には趣味があるからです。デブ上司の妻は仕事と家事をしなければならないので、娘も同時に手伝う必要があります。

このとき、娘はこの2つの親クラスのメソッドを継承して利用する必要があるのですが、どうやって書けばいいのでしょうか?

実装コードを見てみましょう:

# 胖子老板的父类
class FatFather(object):
    def __init__(self, name, *args, **kwargs):
        print()
        print("=============== 开始调用 FatFather  ========================")
        print(&#39;FatFather的init开始被调用&#39;)
        self.name = name
        print(&#39;调用FatFather类的name是%s&#39; % self.name)
        print(&#39;FatFather的init调用结束&#39;)
        print()
        print("=============== 结束调用 FatFather  ========================")
# 胖子老板类 继承 FatFather 类
class FatBoss(FatFather):
    def __init__(self, name, hobby, *args, **kwargs):
        print()
        print("=============== 开始调用 FatBoss  ========================")
        print(&#39;胖子老板的类被调用啦!&#39;)
        #super().__init__(name)
        ## 因为多继承传递的参数不一致,所以使用不定参数
        super().__init__(name, *args, **kwargs)
        print("%s 的爱好是 %s" % (name, hobby))
        print()
        print("=============== 结束调用 FatBoss  ========================")
# 胖子老板的老婆类 继承 FatFather类
class FatBossWife(FatFather):
    def __init__(self, name, housework, *args, **kwargs):
        print()
        print("=============== 开始调用 FatBossWife  ========================")
        print(&#39;胖子老板的老婆类被调用啦!要学会干家务&#39;)
        #super().__init__(name)
        ## 因为多继承传递的参数不一致,所以使用不定参数
        super().__init__(name, *args, **kwargs)
        print("%s 需要干的家务是 %s" % (name, housework))
        print()
        print("=============== 结束调用 FatBossWife  ========================")
# 胖子老板的女儿类 继承 FatBoss FatBossWife类
class FatBossGril(FatBoss, FatBossWife):
    def __init__(self, name, hobby, housework):
        print(&#39;胖子老板的女儿类被调用啦!要学会干家务,还要会帮胖子老板斗地主&#39;)
        super().__init__(name, hobby, housework)
def main():
    print("打印FatBossGril类的MRO")
    print(FatBossGril.__mro__)
    print()
    print("=========== 下面按照 MRO 顺序执行super方法 =============")
    gril = FatBossGril("胖子老板", "打斗地主", "拖地")

実行結果は次のとおりです:

if __name__ == "__main__":
    main()
打印FatBossGril类的MRO
(<class &#39;__main__.FatBossGril&#39;>, <class &#39;__main__.FatBoss&#39;>, <class &#39;__main__.FatBossWife&#39;>, 
<class &#39;__main__.FatFather&#39;>, <class &#39;object&#39;>)
=========== 下面按照 MRO 顺序执行super方法 =============
胖子老板的女儿类被调用啦!要学会干家务,还要会帮胖子老板斗地主
=============== 开始调用 FatBoss  ========================
胖子老板的类被调用啦!
=============== 开始调用 FatBossWife  ========================
胖子老板的老婆类被调用啦!要学会干家务
=============== 开始调用 FatFather  ========================
FatFather的init开始被调用
调用FatFather类的name是胖子老板
FatFather的init调用结束
=============== 结束调用 FatFather  ========================
胖子老板 需要干的家务是 拖地
=============== 结束调用 FatBossWife  ========================
胖子老板 的爱好是 打斗地主
=============== 结束调用 FatBoss  ========================

上記の実行結果から、意図的に開始と終了を与えます。各クラスへの呼び出しはすべて印刷され、マークされており、見ることができます。

各クラスの開始呼び出しは、MRO シーケンスに従って開始され、1 つずつ終了します。

また、異なる親クラスを継承する必要があるため、パラメータは必ずしも確実ではありません。

したがって、すべての親クラスは変数パラメーター *args および **kwargs を追加する必要があります。追加しないと、パラメーターが一致しない場合にエラーが報告されます。

3. 注意事項

· Super().init は、単一継承のクラス名.init と基本的に使用方法に違いはありません。

#ただし、多重継承には違いがあります。スーパー メソッドでは、各親クラスのメソッドが 1 回だけ実行されるようにできますが、クラス名を使用するメソッドでは、メソッドが実行されます。コードを書いて出力を確認してみてください。

#多重継承を使用する場合は、スーパー メソッドを使用してパラメータを親クラスに渡します。これは Python のスーパー アルゴリズムによるものです。すべてのパラメータを渡す必要があります。渡さないとエラーになります。報告されます。

#単一継承を使用する場合、スーパーメソッドを使用すると、すべてのパラメータを渡すことはできません。親クラスのメソッドで必要なパラメータのみを渡すことができ、それ以外の場合はエラーが発生します。報告。

#多重継承を使用する場合、クラス名.init メソッドを使用する場合と比較して、すべての親クラスを一度に記述する必要がありますが、スーパー メソッドを使用すると、1 つだけ記述するだけで済みます。すべてを実行する文 親クラスのメソッド。これは、多重継承ですべてのパラメータを渡す必要がある理由の 1 つでもあります。

4. 演習

次のコードの出力は何になりますか? 答えて説明してください。

class Parent(object):
    x = 1
class Child1(Parent):
    pass
class Child2(Parent):
    pass
print(Parent.x, Child1.x, Child2.x)
1 1 1
Child1.x = 2
print(Parent.x, Child1.x, Child2.x)
1 2 1

注: Child1 はすでに自分の x

Parent.x = 3
print(Parent.x, Child1.x, Child2.x)
3 2 3
を持っています

以上がPythonのsuper()メソッドの詳しい解説の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はjianshu.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。