Caution

お使いのブラウザはJavaScriptが実行できない状態になっております。
当サイトはWebプログラミングの情報サイトの為、
JavaScriptが実行できない環境では正しいコンテンツが提供出来ません。
JavaScriptが実行可能な状態でご閲覧頂くようお願い申し上げます。

Python辞典

  1. トップページ
  2. Python辞典
  3. 継承 / super() / 多重継承

継承 / super() / 多重継承

Pythonでは『class 子クラス(親クラス)』という構文でクラスを継承します。子クラスは親クラスのメソッドとプロパティを引き継ぎ、必要に応じてオーバーライド(上書き)できます。『super()』は親クラスのメソッドを呼び出すために使います。Pythonは多重継承をサポートしており、複数の親クラスを持つクラスを定義できますが、設計が複雑になるため注意が必要です

構文
# 継承
class 子クラス(親クラス):
    def __init__(self, ...):
        super().__init__(...)    # 親の__init__を呼び出す

# メソッドのオーバーライド
    def メソッド(self):
        super().メソッド()       # 親のメソッドも呼ぶ場合
        # 追加の処理

# 多重継承
class 子クラス(親1, 親2):
    pass
構文・関数一覧
構文・関数概要
class 子(親)親クラスを継承した子クラスを定義する。
super()親クラス(またはMROの次のクラス)を参照するオブジェクトを返す。
super().__init__()親クラスの初期化メソッドを呼び出す。
class 子(親1, 親2)複数の親クラスを持つ多重継承のクラスを定義する。
クラス.__mro__MRO(メソッド解決順序)をタプルで返す属性。
サンプルコード
# 基本的な継承
class Animal:
    def __init__(self, name):
        self.name = name

    def speak(self):
        return f"{self.name}が鳴いています"

    def __str__(self):
        return f"{self.__class__.__name__}({self.name})"

class Dog(Animal):
    def __init__(self, name, breed):
        super().__init__(name)      # 親の__init__を呼ぶ
        self.breed = breed          # 子クラス固有の属性

    def speak(self):                # メソッドのオーバーライド
        return f"{self.name}がワンワンと鳴いています"

    def fetch(self):                # 子クラス固有のメソッド
        return f"{self.name}がボールを取ってきました!"

class Cat(Animal):
    def speak(self):
        return f"{self.name}がニャーと鳴いています"

d = Dog('ポチ', '柴犬')
c = Cat('タマ')

print(d.speak())    # ポチがワンワンと鳴いています
print(c.speak())    # タマがニャーと鳴いています
print(d.fetch())    # ポチがボールを取ってきました!
print(d.breed)      # 柴犬

# isinstance で継承関係を確認
print(isinstance(d, Dog))       # True
print(isinstance(d, Animal))    # True(Animalも継承している)

# super()でオーバーライドしつつ親も呼ぶ
class GuideDog(Dog):
    def speak(self):
        base = super().speak()  # Dogのspeakを呼ぶ
        return f"{base}(盲導犬)"

gd = GuideDog('ラブ', 'ラブラドール')
print(gd.speak())   # ラブがワンワンと鳴いています(盲導犬)

# 多重継承とMRO(C3線形化アルゴリズム)
class Flyable:
    def move(self):
        return "飛んでいます"

class Swimmable:
    def move(self):
        return "泳いでいます"

class Duck(Flyable, Swimmable):
    pass

duck = Duck()
print(duck.move())          # 飛んでいます(Flyableが先に解決される)
print(Duck.__mro__)         # MROの順序を確認
# (<class 'Duck'>, <class 'Flyable'>, <class 'Swimmable'>, <class 'object'>)
概要

MRO(Method Resolution Order)とはメソッドを検索する順序で、Pythonはクラスの継承ツリーをC3線形化アルゴリズムで解決します。『クラス.__mro__』で確認でき、多重継承時にどのクラスのメソッドが優先されるかを決定します。

子クラスで『__init__()』を定義する際は、基本的に親の『__init__()』をsuper()で呼ぶ必要があります。呼ばないと親クラスの初期化が行われず、親クラスのインスタンス変数が設定されないため、親クラスのメソッドを呼び出すとエラーになります。

多重継承はコードの複雑度を高めるため、可能であれば「コンポジション(合成)」パターン(継承より委譲)で代替することが推奨されます。Mixinクラス(特定の機能だけを追加するための親クラス)として使う場合は多重継承が有効です。

記事の間違いや著作権の侵害等ございましたらお手数ですがまでご連絡頂ければ幸いです。