このページで解説している内容は、以下の YouTube 動画の解説で見ることができます。

【Python入門】派生と継承

派生と継承

 オブジェクト指向プログラミングでは、似たような機能を持つ複数のクラスが登場することがあります。派生と継承を活用すると、共通の処理や属性を一箇所にまとめることができ、プログラム全体がシンプルかつ保守しやすくなります。ここでは、基底クラスに共通の機能をまとめ、そこから派生クラスを定義することで、重複コードを削減する仕組みについて解説します。

プログラムのダウンロード

 「ダウンロード」から、JupyterLab で実行できるサンプルプログラムがダウンロードできます。ファイルは、ESET Endpoint Securityでウイルスチェックをしておりますが、ダウンロードとプログラムの実行は自己責任でお願いいたします。

1.派生と継承の基本概念

1.1. 派生(継承)とは

 派生とは、既存のクラス(基底クラスまたは親クラス)の機能を引き継ぎ、新たなクラス(派生クラスまたは子クラス)を定義する手法です。派生クラスは、基底クラスのデータ属性やメソッドを再利用できるため、プログラムの記述量を大幅に削減できます。

1.2. クラスの継承関係

下図は、基底クラスと派生クラスの関係を示したものです。

 このように、派生クラスは基底クラスの共通機能を引き継ぎつつ、各クラス固有の属性や処理を追加することができます。

2.継承を使わずに定義した場合の例

ここでは、まず継承を使わずに、BookクラスとCDクラスを個別に定義する例を示します。

 以下は、継承を使わずにそれぞれのクラスを定義し、オブジェクトを生成して内容を表示するプログラムです。

# Bookクラスの定義(継承を使わない場合)
class Book:
    def __init__(self, title, price, publication_year):
        # オブジェクト生成時に、書籍のタイトル、価格、出版年を初期化する
        self.title = title
        self.price = price
        self.publication_year = publication_year

    def show(self):
        # 書籍の情報を表示するメソッド
        print('Title:', self.title)
        print('Price:', self.price)
        print('Publication Year:', self.publication_year)

# CDクラスの定義(継承を使わない場合)
class CD:
    def __init__(self, title, price, duration):
        # オブジェクト生成時に、CDのタイトル、価格、再生時間(分)を初期化する
        self.title = title
        self.price = price
        self.duration = duration

    def show(self):
        # CDの情報を表示するメソッド
        print('Title:', self.title)
        print('Price:', self.price)
        print('Duration (min):', self.duration)

# Bookオブジェクトの生成と表示
book1 = Book('Python 101', 30, 2020)
book1.show()

print()  # 改行

# CDオブジェクトの生成と表示
cd1 = CD('Greatest Hits', 15, 90)
cd1.show()

実行結果

Title: Python 101
Price: 30
Publication Year: 2020

Title: Greatest Hits
Price: 15
Duration (min): 90

詳しい解説

  • Bookクラス
    __init__ メソッドでは、書籍タイトル(title)、価格(price)、出版年(publication_year)を受け取り、各データ属性に保存しています。
    show メソッドは、これらの情報をコンソールに表示します。
  • CDクラス
    ・同様に、__init__ メソッドでCDのタイトル、価格、再生時間(duration)を初期化し、show メソッドで出力します。
  • オブジェクト生成と表示
    book1 = Book('Python 101', 30, 2020) により、Bookクラスのインスタンスが生成され、その後 book1.show() によって書籍の情報が出力されます。
    cd1 = CD('Greatest Hits', 15, 90) により、CDクラスのインスタンスが生成され、cd1.show() によってCDの情報が表示されます。

3.継承を用いて定義した場合の例

 派生クラス(サブクラス)を定義することで、既存のクラス(基底クラス、または親クラス)の機能をそのまま再利用しつつ、必要な部分だけを拡張・変更することができます。これにより、コードの重複を防ぎ、プログラムを簡潔に保つことが可能となります。

3.1. 派生クラスの定義方法

基本的な構文は以下のとおりです。

class 派生クラス名(基底クラス名, ...):
    # 派生クラスの定義文
  • 単一継承
    1つの基底クラスのみを継承する場合を「単一継承」と呼びます。
  • 多重継承
    2つ以上の基底クラスを継承する場合は、基底クラス名をカンマで区切って指定します。Pythonは多重継承に対応しており、複数のクラスから機能を引き継ぐことが可能です。

3.2. 単一継承の例

 以下は、単一継承を用いて共通の機能をまとめた例です。ここでは、Item クラスを基底クラスとして定義し、そこから Book クラスと CD クラスを派生クラスとして作成します。

# 基底クラス Item の定義
class Item:
    def __init__(self, title, price):
        # すべてのアイテムで共通するデータ属性
        self.title = title
        self.price = price

    def show(self):
        # 共通の情報を表示するメソッド
        print("Title:", self.title)
        print("Price:", self.price)

# 派生クラス Book の定義(Item クラスを継承)
class Book(Item):
    def __init__(self, title, price, publication_year):
        # 基底クラスの初期化を呼び出す
        super().__init__(title, price)
        # Book クラス固有のデータ属性
        self.publication_year = publication_year

    def show(self):
        # 基底クラスの show メソッドを呼び出して共通情報を表示し、
        # さらに出版年を追加で表示する
        super().show()
        print("Publication Year:", self.publication_year)

# 派生クラス CD の定義(Item クラスを継承)
class CD(Item):
    def __init__(self, title, price, duration):
        # 基底クラスの初期化を呼び出す
        super().__init__(title, price)
        # CD クラス固有のデータ属性
        self.duration = duration  # 再生時間(分)

    def show(self):
        # 基底クラスの show メソッドを呼び出して共通情報を表示し、
        # さらに再生時間を追加で表示する
        super().show()
        print("Duration (min):", self.duration)

# オブジェクトの生成とメソッドの呼び出し

# Book オブジェクトを生成(タイトル、価格、出版年)
book1 = Book("Advanced Python", 45, 2022)
book1.show()

print()  # 出力の区切りのため改行

# CD オブジェクトを生成(タイトル、価格、再生時間)
cd1 = CD("Greatest Hits", 20, 75)
cd1.show()

実行結果

Title: Advanced Python
Price: 45
Publication Year: 2022

Title: Greatest Hits
Price: 20
Duration (min): 75

詳しい解説

  1. 基底クラス Item
    定義
    Item クラスは、すべてのアイテムに共通する属性として title(タイトル)と price(価格)を持ち、これらを __init__ メソッドで初期化します。
    メソッド show
    このメソッドでは、共通の情報であるタイトルと価格を出力します。
  2. 派生クラス Book
    継承
    Book クラスは Item クラスを継承しています。これにより、BookItem の属性とメソッド(ここでは titlepriceshow)を自動的に受け継ぎます。
    初期化の拡張
    __init__ メソッドでは、まず super().__init__(title, price) を呼び出すことで、基底クラスの初期化処理を実行し、共通の属性を設定します。その後、publication_year(出版年)という Book 固有の属性を追加で初期化します。
    メソッド show のオーバーライド
    Book クラスでは、show メソッドをオーバーライドして、まず基底クラスの show を呼び出し、共通情報を表示した後に出版年を表示します。
  3. 派生クラス CD
    継承
    CD クラスも Item クラスを継承しており、共通の属性(titleprice)を受け継ぎます。
    初期化の拡張
    __init__ メソッドで super().__init__(title, price) を呼び出した後、duration(再生時間)というCD固有の属性を初期化します。
    メソッド show のオーバーライド
    基底クラスの show を呼び出し、共通の情報を表示した後に再生時間を追加で表示します。
  4. オブジェクト生成とメソッド呼び出し
    book1 = Book("Advanced Python", 45, 2022) により、Book クラスのインスタンスが生成され、show() を呼び出すとタイトル、価格、出版年が表示されます。
    ・同様に、cd1 = CD("Greatest Hits", 20, 75) により CD オブジェクトが生成され、show() の呼び出しでタイトル、価格、再生時間が表示されます。

 このように、継承を利用することで、共通の機能を基底クラスにまとめ、派生クラスでは固有の情報のみを追加・オーバーライドする形で実装でき、コードの重複が大幅に削減され、プログラム全体の可読性と保守性が向上します。

まとめ

 継承(派生)を活用すると、複数のクラス間で共通する機能(例えば、title と price、または情報を表示する show メソッド)をひとまとめにして再利用できるため、プログラムがよりシンプルになり、保守性も向上します。今回の例では、継承を使わずにBookクラスとCDクラスを個別に定義しましたが、これらの共通部分を基底クラス(例えば、Itemクラス)に抽出すれば、コードの重複を大幅に削減できます。