読み込み中...

Python多重継承完全ガイド!基礎から応用までの10ステップ

Pythonの多重継承のステップバイステップガイドのサムネイル画像 Python
この記事は約11分で読めます。

【サイト内のコードはご自由に個人利用・商用利用いただけます】

この記事では、プログラムの基礎知識を前提に話を進めています。

説明のためのコードや、サンプルコードもありますので、もちろん初心者でも理解できるように表現してあります。

本記事のサンプルコードを活用して機能追加、目的を達成できるように作ってありますので、是非ご活用ください。

※この記事は、一般的にプロフェッショナルの指標とされる『実務経験10,000時間以上』を満たす現役のプログラマチームによって監修されています。

※Japanシーモアは、常に解説内容のわかりやすさや記事の品質に注力しております。不具合、分かりにくい説明や不適切な表現、動かないコードなど気になることがございましたら、記事の品質向上の為にお問い合わせフォームにてご共有いただけますと幸いです。
(送信された情報は、プライバシーポリシーのもと、厳正に取扱い、処分させていただきます。)

はじめに

プログラミングの世界は広大で、その中でもPythonという言語はその柔軟性から多くの開発者に愛されています。

本記事ではPythonの特徴的な概念である「多重継承」を11ステップで詳しく学んでいきます。

初心者から上級者まで、誰でもPythonの多重継承の基礎から応用までを理解できる内容となっています。

●Pythonとは?

Pythonは高水準の汎用プログラミング言語で、その独自の文法と高い可読性により、初学者から経験豊富なプログラマまで幅広く利用されています。

Pythonは、機械学習、ウェブ開発、スクリプト作成など、様々な場面でその力を発揮します。

●オブジェクト指向とは?

オブジェクト指向は、プログラミングの設計思想の一つで、現実世界の物事を「オブジェクト」として捉え、それらが相互に作用することでシステムを表現しようとする考え方です。

Pythonもオブジェクト指向を採用した言語で、クラスとオブジェクト、継承などの概念を用いてより直感的なコードを記述することが可能です。

●Pythonにおけるクラスとは?

Pythonにおけるクラスは、オブジェクト指向プログラミングの基本的な概念で、関連する変数とメソッドをまとめたものを指します。

これにより、共通の性質や動作を持つオブジェクトを簡単に作成することができます。

●Pythonにおける継承とは?

継承とは、あるクラスの属性やメソッドを別のクラスが引き継ぐことを指します。

これによりコードの重複を避け、プログラムの構造をシンプルに保つことができます。

Pythonでは単一継承だけでなく、多重継承もサポートされています。

○単一継承のサンプルコード

下記のコードでは、単一継承の例を紹介しています。

この例では、親クラスAnimalから子クラスDogが属性とメソッドを継承しています。

class Animal:
    def __init__(self, name):
        self.name = name

    def speak(self):
        return 'unknown'

class Dog(Animal):
    def speak(self):
        return 'bark'

my_dog = Dog('Pochi')
print(my_dog.name)  # Pochi
print(my_dog.speak())  # bark

上記のコードを実行すると、「Pochi」と「bark」が出力されます。

DogクラスはAnimalクラスのメソッドspeakをオーバーライド(上書き)しているため、「bark」が出力されることになります。

●Pythonにおける多重継承とは?

Pythonの多重継承とは、一つのクラスが複数の親クラスから属性やメソッドを継承できる機能を指します。

これにより、複数のクラスの機能を一つのクラスが持つことが可能となりますが、注意しなければならないポイントも存在します。

それらについては後ほど詳しく解説します。

○多重継承のサンプルコード1:基本的な使い方

下記のコードでは、Pythonの多重継承の基本的な使い方を紹介しています。

この例では、AnimalクラスとWorkクラスからDogクラスが属性とメソッドを継承しています。

class Animal:
    def __init__(self, name):
        self.name = name

class Work:
    def __init__(self, job):
        self.job = job

class Dog(Animal, Work):
    def __init__(self, name, job):
        Animal.__init__(self, name)
        Work.__init__(self, job)

my_dog = Dog('Pochi', 'Police')
print(my_dog.name)  # Pochi
print(my_dog.job)  # Police

このコードを実行すると、「Pochi」と「Police」が出力されます。

DogクラスはAnimalクラスとWorkクラスの両方から継承しているため、それぞれの属性である’name’と’job’を持つことができます。

○多重継承のサンプルコード2:メソッドのオーバーライド

Pythonで多重継承を用いた際の重要な技術としてメソッドのオーバーライドがあります。

オーバーライドとは、親クラスで定義したメソッドを子クラスで再定義することです。

これにより、子クラスの特性に合わせたメソッドの挙動を実現できます。

下記のコードでは、PersonとEmployeeの2つの親クラスを持つManagerクラスを定義し、親クラスのメソッドをオーバーライドしています。

Personクラスではsay_helloメソッドを定義し、Employeeクラスではworkメソッドを定義します。

これらのメソッドは、Managerクラスでは異なる振る舞いをするためにオーバーライドします。

class Person:
    def say_hello(self):
        return "こんにちは"

class Employee:
    def work(self):
        return "働いています"

class Manager(Person, Employee):
    def say_hello(self):
        return super().say_hello() + ", 私はマネージャーです"
    def work(self):
        return super().work() + "、リーダーシップを発揮しています"

manager = Manager()
print(manager.say_hello())
print(manager.work())

この例では、Managerクラスではsay_helloメソッドとworkメソッドがオーバーライドされており、それぞれ異なるメッセージを返すようになっています。

さらに、オーバーライドされたメソッド内でsuper()を使用することで親クラスのメソッドを呼び出すことができます。

これにより、既存のメソッドを完全に新しいものに書き換えるのではなく、既存の機能を拡張することが可能となります。

このコードを実行すると、次の結果が出力されます。

こんにちは, 私はマネージャーです
働いています、リーダーシップを発揮しています

この結果から、オーバーライドされたメソッドが正しく機能し、親クラスのメソッドを適切に拡張できていることがわかります。

○多重継承のサンプルコード3:super()の使い方

次に、Pythonの多重継承で重要なsuper()の使い方について見ていきましょう。

super()は、子クラスから親クラスのメソッドを呼び出すための組み込み関数です。

下記のコードでは、さきほどのManagerクラスに加えて、更にその子クラスであるExecutiveクラスを定義しています。

Executiveクラスではsay_helloメソッドをオーバーライドし、さらにその中でsuper()を使用して親クラスのsay_helloメソッドを呼び出しています。

class Executive(Manager):
    def say_hello(self):
        return super().say_hello() + ", さらにエグゼクティブでもあります"

executive = Executive()
print(executive.say_hello())

この例では、Managerクラスでオーバーライドされたsay_helloメソッドを、Executiveクラスでさらにオーバーライドしています。

しかし、その中でsuper().say_hello()を使用することで、親クラスであるManagerクラスのsay_helloメソッドを呼び出し、その結果を基に新たなメッセージを生成しています。

このコードを実行すると、次の結果が出力されます。

こんにちは, 私はマネージャーです, さらにエグゼクティブでもあります

これにより、super()を使って親クラスのメソッドを呼び出し、その結果を拡張することで、メソッドの振る舞いを階層的に定義することができることがわかります。

●多重継承の注意点と対処法

Pythonでの多重継承には、特に注意が必要な点とそれに対する対処法がいくつか存在します。まず一つ目は、メソッドの衝突問題です。

これは二つ以上のスーパークラスが同じメソッドを持つ場合に、どのメソッドを呼び出すべきかが曖昧になる問題です。

この問題を解決するためには、具体的なメソッドの呼び出し順序を定義するか、メソッドのオーバーライドを適切に行う必要があります。

また二つ目は、いわゆる「ダイヤモンド問題」です。

これは、二つのスーパークラスが同一のスーパークラスを持つ場合に発生する問題で、最終的なサブクラスが同一のメソッドを二度受け継ぐことになり、意図しない挙動を引き起こす可能性があります。

この問題に対する対処法については、後述の項目で詳しく説明します。

○ダイヤモンド問題とは?

ダイヤモンド問題とは、あるクラスが二つ以上のクラスから継承し、それらの親クラスが同一のスーパークラスを共有する場合に発生します。

この問題を説明するためには、下記のサンプルコードが役立つでしょう。

class A:
    def foo(self):
        print('Aのfooメソッド')

class B(A):
    def foo(self):
        print('Bのfooメソッド')

class C(A):
    def foo(self):
        print('Cのfooメソッド')

class D(B, C):
    pass

d = D()
d.foo()

このコードでは、DクラスはBクラスとCクラスから継承しており、BクラスとCクラスは共にAクラスから継承しています。

最終的なDクラスのインスタンスdfooメソッドを呼び出した場合、どのfooメソッドが実行されるのかがダイヤモンド問題の要点です。

この例を実行すると、「Bのfooメソッド」と表示されます。

Pythonでは、クラスDの親クラスを探索する際、左から右の順で探索するため、先に見つかったBクラスのfooメソッドが実行されるのです。

○メソッド解決順序(MRO)とは?

ダイヤモンド問題を解決するためには、Pythonのメソッド解決順序(MRO)という仕組みを理解する必要があります。

MROは、多重継承がある場合に、どの順番でスーパークラスを探索するかを定めたものです。

Pythonでは、C3線形化というアルゴリズムを使って、クラスの探索順序を決定します。

これにより、どのクラスのメソッドが呼び出されるのかが一意に決まり、ダイヤモンド問題を回避することが可能になります。

MROはmroメソッドや__mro__属性を使って確認することができます。

例えば、上述したダイヤモンド問題の例でMROを見てみると次のようになります。

print(D.mro())
# [<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]

この結果から、PythonがDクラスのメソッドを探索する際の順番がわかります。

先にD自身を見て、次にB、その次にC、そしてA、最後にobjectを見るという順序です。

これがMROの仕組みであり、このようにしてダイヤモンド問題が解決されるのです。

まとめ

今回の記事ではPythonの多重継承の基礎から応用までを11のステップで解説しました。

Pythonの多重継承は、コードの再利用性を高め、より高度な機能を持つクラスを設計するための重要な手段です。

それぞれのクラスが一部の特性だけを持つよう設計することで、組み合わせて多様な機能を持つ新たなクラスを作ることが可能です。

一方で、多重継承の適切な使用法と注意点を理解することが重要です。

特にメソッドの衝突やダイヤモンド問題などは深く理解しておくべきです。

また、本記事ではmixinクラスという特定の機能だけを提供するクラスを使った多重継承のカスタマイズ例についても触れました。

このようなカスタマイズを通じて、Pythonの多重継承がどのようにプログラムの設計やコードの再利用性を向上させるかを学びました。

Pythonでの多重継承は非常に強力なツールですが、それを最大限に活用するには適切な知識と理解が必要です。

本記事がPythonでの多重継承を理解し、実践的に活用するための一助になれば幸いです。

最後に、多重継承に関する知識は理論だけでなく、実際に手を動かし、コードを書くことでより深く理解できます。

本記事で提供したサンプルコードを活用し、自身で試してみることをおすすめします。

これにより、Pythonの多重継承の概念とその活用方法についてより深い理解を得ることができるでしょう。

それでは、Pythonでのコーディングライフを楽しんでください。