0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

なんとなく使ってない?Pythonの super() を正しく理解する

Posted at

はじめに

Pythonでクラスを継承してると、ついこう思ったことありませんか?

super()? なんか親クラス呼ぶやつでしょ?」

実はそれ、半分正解で半分間違いです。
super() は単に「親」を呼ぶのではなく、MRO(メソッド解決順序) という仕組みに従って「次に呼ぶべきクラス」を決めています。

この仕組みを理解していないと、多重継承やフレームワーク利用時に思わぬバグにハマることも…。

この記事では、super() の基本からMRO、多重継承の動き、実務での使い所、そして落とし穴までをまとめます。
「なんとなく使ってる」から「正しく使いこなす」へ、一段レベルアップしましょう!


💡 super()って何者?

「親を呼ぶ関数」だと思われがちですが、実際は MROに沿って次のクラスを呼ぶバトンリレー です。
Python3 以降なら、引数なしでシンプルに書けます。

🔰 基本の使い方

class Parent:
    def greet(self):
        print("Hello from Parent")


class Child(Parent):
    def greet(self):
        print("Hello from Child")
        super().greet()  # ← 親クラスの greet を呼ぶ


c = Child()
c.greet()

出力:

Hello from Child
Hello from Parent

➡️ super().greet() で親クラスの greet メソッドを呼べていることがわかります。


🔰 Python2の場合(補足)

Python2 では、super() を呼ぶときに 「自分のクラス」と「self」 を明示的に渡す必要がありました。

class Child(Parent):
    def greet(self):
        print("Hello from Child")
        super(Child, self).greet()  # ← クラスとインスタンスを指定

Python3 ではこれが不要になり、シンプルに super().method() でOK。
可読性も保守性も段違いに良くなっています。


⚙️ 多重継承の正体はMROだった!

複雑そうに見える多重継承も、MROを知れば仕組みはシンプルです。

例:単純な多重継承

class A:
    def greet(self):
        print("Hello from A")

class B(A):
    def greet(self):
        print("Hello from B")
        super().greet()

class C(A):
    def greet(self):
        print("Hello from C")
        super().greet()

class D(B, C):
    def greet(self):
        print("Hello from D")
        super().greet()

d = D()
d.greet()

出力:

Hello from D
Hello from B
Hello from C
Hello from A

➡️ 実行すると、D → B → C → A の順で呼ばれます。

この順序は C3線形化アルゴリズム で決まっていますが、細かい説明は割愛。
今回の例で重要なのは次の3点だけ。

  1. 定義で D(B, C) と書いたので BC より優先
  2. B の中では「B が A より前」
  3. C の中では「C が A より前」

結果として D → B → C → A の順序になる、というわけです。


💡 継承関係がややこしいときは mro() を使えば一発!

print(D.mro())

出力:

[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]

👉 どの順番で呼ばれるか、確認できれば怖くない!


🚀 super()を使うとコードがスッキリ!

「親クラスを直呼び」しても動くけど、冗長で読みにくい…。
そんなとき super() に置き換えるとスッキリします。

1. 直呼びコード(動くけど冗長)

class Base:
    def process(self):
        print("Base process")


class Logger(Base):
    def process(self):
        print("Logger start")
        Base.process(self)   # 親を直呼び
        print("Logger end")


class Auth(Logger):
    def process(self):
        print("Auth check")
        Logger.process(self)  # 親を直呼び
        print("Auth done")


a = Auth()
a.process()

出力:

Auth check
Logger start
Base process
Logger end
Auth done

👉 結果は正しいけど、親クラス名をべた書きしているので、継承関係を変えたら全部修正が必要。


2. superに置き換えたコード(スッキリ!)

class Base:
    def process(self):
        print("Base process")


class Logger(Base):
    def process(self):
        print("Logger start")
        super().process()   # superでスッキリ
        print("Logger end")


class Auth(Logger):
    def process(self):
        print("Auth check")
        super().process()   # superでスッキリ
        print("Auth done")


a = Auth()
a.process()

出力:

Auth check
Logger start
Base process
Logger end
Auth done

👉 動きは同じ。でも super() にするだけで:

  • 親クラス名を直接書かなくていい
  • 継承関係を変えても修正不要
  • 多重継承でもMROに従って安全

コードの見通しが圧倒的に良くなります。


🎯 まとめ:super()は速くならない。でもコードは強くなる

正直、super() を使っても処理速度が爆速になるわけではありません。
でも――

  • 可読性が上がる
  • 余計な記述が減る
  • 継承関係を変えても壊れない

これだけで十分、実務では大きな武器になります。

「なんとなく親呼ぶやつ」と思っていた super() は、実は “Pythonらしい継承” を支えるキーパーツ
知っているかどうかで、コードの綺麗さと安心感はまるで違います。

👉 ぜひ自分のコードでも super() を積極的に取り入れてみてください!

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?