superとは?
Pythonのsuperとは、クラスの継承において、親クラス(スーパークラス)のメソッドを呼び出すための組み込み関数です。子クラス(サブクラス)から、親クラスが持っている機能(メソッド)を使いたいときに活躍します。
以前は親クラスの名前を直接指定して呼び出す方法もありましたが、superを使うとコードのメンテナンスがしやすくなります。例えば、親クラスの名前が変わった場合でも、superで書かれた部分を修正する必要がありません。
また、複数の親クラスを持つ多重継承の仕組みを使うときに特に役立ちます。superは、Pythonが定めた呼び出し順序(MRO: Method Resolution Order)に従って、適切な親クラスの機能を自動で呼び出してくれます。
superを活用すると、同じコードを何度も書くことを避ける「DRY原則(Don't Repeat Yourself)」を守りやすくなり、コード全体を簡潔に保てます。
superの特徴
- 親クラス(スーパークラス)のメソッドを呼び出すために使う
- 親クラス名を直接指定する必要がなくなりコードの保守性が向上する
- 親クラスの名前が変更されても呼び出し側を修正する必要がない
- 多重継承の際に適切な順序(MRO)で親クラスのメソッドを自動で呼び出す
- コードの重複を減らし簡潔さを保つ「DRY原則」の維持に役立つ
【関連】
Pythonをもっと詳しく学ぶならpaizaラーニング
基本構文
Python superの基本的な使い方を見てみましょう。一般的な構文は以下のとおりです。
具体的な例として、シンプルな継承関係を表現してみましょう。
出力結果
なにか音を出します
ワン!ワン!この例では、イヌクラスがどうぶつクラスの鳴く()メソッドをオーバーライド(上書き)しています。イヌクラスの鳴く()メソッド内では、まずsuper().鳴く()によって親クラス(どうぶつ)の鳴く()が呼び出され、「なにか音を出します」が出力されます。その後、イヌクラス独自の処理として「ワン!ワン!」が出力されています。
次に、クラスが作られるとき(インスタンス化)に自動で呼ばれるコンストラクタ(__init__メソッド)で使う例を見てみましょう。
出力結果
タマというどうぶつを作成しました
タマは3歳ですこの例では、ネコクラスのコンストラクタ(__init__)でsuperを使い、親クラス(どうぶつ)のコンストラクタを呼び出しています。
親クラスの処理で「タマというどうぶつを作成しました」が出力され、その後、子クラスの処理で「タマは3歳です」が出力されます。親クラスの初期化処理を再利用しつつ、子クラス独自の処理を追加する定番の使い方です。
実用例
super関数の理解を深めるために、さまざまな実用例を見ていきましょう。各例では、実際のコードとその説明を通じて、superがどのように役立つかを示します。
単純な継承でのメソッド拡張
親クラスのメソッドを拡張する最も基本的な使い方です。
出力結果
ニンジンを見つけました
食べものを食べていますこの例では、ウサギクラスの食べる()メソッドが呼ばれると、まず「ニンジンを見つけました」が出力されます。
次にsuper().食べる()によって親クラス(どうぶつ)の食べる()メソッドが実行され、「食べものを食べています」が出力されます。super()を使い親クラスの機能を再利用することで、コードの重複を避けられます。
コンストラクタの拡張と属性の追加
子クラスで新しい属性を追加する場合の例です。
出力結果
ポチは柴犬ですこの例では、イヌクラスのインスタンス作成時にsuper().__init__("ポチ")が呼ばれ、親クラス(どうぶつ)でself.名前が設定されます。
その後、子クラス(イヌ)でself.品種が設定されます。super()を使うことで、名前属性に関する初期化コードを親クラスに任せ、子クラスでは品種属性の追加に集中できています。
多重継承における活用
superが特に力を発揮するのが、複数の親クラスを持つ多重継承の場合です。
出力結果
ニャーと鳴きます
肉を食べます
体温が一定ですこの例では、ネコクラスの特徴()が呼ばれると、まず「ニャーと鳴きます」が出力されます。
次にsuper().特徴()が、MRO(メソッド解決順序)に従い肉食動物クラスの特徴()を呼び出します。そこでもsuper()が呼ばれ、最終的に哺乳類クラスの特徴()が呼ばれます。結果として、継承順序(ネコ→肉食動物→哺乳類)に沿って処理が実行されます。
メソッドのオーバーライドと部分的再利用
親クラスの機能の一部だけを変更(オーバーライド)し、他の機能はそのまま使いたい場合に役立ちます。
出力結果
この形の面積は78.5ですこの例では、円クラスのインスタンスで説明()メソッドを呼び出しています。円クラス自身は説明()を定義していませんが、親クラス(形)から継承しています。
親クラスの説明()メソッドは内部でself.面積()を呼び出します。selfは円のインスタンスを指すため、円クラスでオーバーライドされた面積()メソッドが呼ばれ、正しい円の面積が計算されます。
クラスメソッドでのsuperの利用
superは、@classmethodデコレータを付けたクラスメソッド内でも使えます。
出力結果
生物の一種です 泳げる鳥です。この例では、ペンギン.情報()というクラスメソッドを呼び出しています。
ペンギンクラスの情報()メソッド内では、super().情報()によって親クラス(動物種)の情報()メソッドが呼ばれ、「生物の一種です」という文字列が取得されます。そして、その文字列に「 泳げる鳥です。」を追加したものが最終的な結果となります。
プライベートメソッドと組み合わせた例
内部的な処理(ここではアンダースコア_で始まるメソッド)とsuper()を組み合わせる例です。
出力結果
飛ぶしています
70この例では、トリクラスの行動("飛ぶ")が呼ばれています。
まずsuper().行動("飛ぶ")が実行され、親クラスの行動()により「飛ぶしています」が出力され、エネルギーが10消費されます。その後、トリクラスのif文の条件に当てはまるため、追加でエネルギーが20消費されます。最終的なエネルギーは100 - 10 - 20 = 70となります。
継承チェーンでの使用
複数世代にわたる継承(例 A→B→C)でも、superは適切に動作します。
出力結果
Cのメソッド
Bのメソッド
Aのメソッドこの例では、Cクラスのインスタンスcのメソッド()を呼び出しています。まずCのメソッド()が実行され「Cのメソッド」が出力されます。
次にsuper()によってBのメソッド()が呼ばれ「Bのメソッド」が出力されます。さらにsuper()によってAのメソッド()が呼ばれ「Aのメソッド」が出力されます。super()が継承チェーンをさかのぼって順番に処理を実行しているのが分かります。
古い形式のsuper呼び出し
Python 2と互換性を持たせるために、引数を指定する形式も知っておくと役立ちます。
出力結果
なにか音を出します
ガオー!この例では、super(クマ, self).鳴く()という形式で親クラスのメソッドを呼び出しています。
Python 3では引数なしのsuper().鳴く()と書くのが一般的ですが、Python 2ではこのようにクラス名とselfを明示的に指定する必要がありました。現在では主にPython 3の引数なしの形式を使います。
まとめ
Pythonのsuperは、クラスの継承を扱ううえで非常に役立つ組み込み関数です。この記事では、基本的な使い方から多重継承での活用例まで解説しました。
superが活躍する場面
- 親クラスの機能を呼び出しつつ機能を追加したいとき
- 子クラスで親クラスの初期化(__init__)を行いたいとき
- 多重継承で親クラスの機能を順番に呼び出したいとき
superを用いる上で、押さえておきたいポイントを覚えておきましょう。
重要なポイント
- MRO(メソッド解決順序)というルールに従って動作する
- 親クラスの名前を直接書かなくて済むため保守性が上がる
- 引数なしのsuper()を使うのが現在の標準的な書き方
初めてPythonを学ぶ方も、この記事で紹介したsuperを実際に書いて、クラス継承の仕組みを試してみてください。
親クラスの機能をうまく再利用するコードは、実際の開発でよく使用されます。マスターしておけば役立つこと間違いなしです。
ぜひsuperをマスターして、より柔軟で保守性の高いプログラムを作成できるようになりましょう。