オーバーライドでは親クラスのメンバーが引き継がれる

はじめに

本日の仕事でPythonETLの社内共通テンプレートのオーバーライドを行い、親クラスのメソッドや変数を子クラスで引き継いだ。

特に何もしなければ、コンストラクタで定義した初期値などが子クラスに引き継がれる。

こういったことについて書いていきたい。

GPTに出してもらったソースコード

以下のソースコードをGPTに生成してもらった。

base_etl.py

class BaseETL:
    def __init__(self):
        self.source_path = "/data/input.csv"
        self.target_table = "default_table"
        self.batch_id = "0000"
        print(f"[BaseETL] 初期化: source={self.source_path}, target={self.target_table}")

    def extract(self):
        print(f"[BaseETL] extract from {self.source_path}")

    def transform(self):
        print("[BaseETL] default transform")

    def load(self):
        print(f"[BaseETL] load into {self.target_table}")

    def run(self):
        self.extract()
        self.transform()
        self.load()

custom_etl.py

from base_etl import BaseETL

class CustomETL(BaseETL):
    def __init__(self):
        super().__init__()  # 親の初期化処理を呼ぶ(source_pathなどを継承)
        self.target_table = "custom_table"  # 一部の初期値だけ変更

    def transform(self):
        print("[CustomETL] 独自の変換処理")

# 実行
if __name__ == "__main__":
    etl = CustomETL()
    etl.run()

このソースコードの処理を追っていこう。

その過程で、オーバーライドについての理解を深めていく。

フォルダ構成

フォルダ構成はこちら。__pycache__は気にしないで欲しい。

templateの上の階層には、Pythonの仮想環境のvenvがある。

custom_etl.pyの実行結果

(.venv) hiroki@shibatahiroshitakanoiMac Python % /Users/hiroki/Downloads/Python/.venv/bin/python /Users/hiroki/Downloads/Python/override/template/custom_etl.py
[BaseETL] 初期化: source=/data/input.csv, target=default_table
[BaseETL] extract from /data/input.csv
[CustomETL] 独自の変換処理
[BaseETL] load into custom_table

処理の流れ

  1. CustomETLクラスのインスタンス生成
  2. runメソッドの実行
  3. extractメソッドの実行
  4. transformメソッドの実行
  5. loadメソッドの実行

3、4、5は2のrunメソッドで実行している。

なにはともあれ、細かく見ていこう。

その方が理解が深まる。

CuntomETLクラスのインスタンス生成

custom_etl.py

12行目はPythonお決まりのmainを実行するための条件文(もう少し解像度高く説明できるようになりたい)。

なにはともあれ、この後にメイン処理の関数を記述する。

13行目で、CustomETLクラスのインスタンスをetlに代入している。

CustomETLクラス

base_etl.pyのBaseETLクラスを継承している。

コンストラクタと、transformの処理がある。

コンストラクタでは、親の初期化処理を呼んでいる。

親の初期化処理

source_path、target_table、batch_idを定義して、「[BaseETL] 初期化: source=/data/input.csv, target=default_table」をコンソールに出力している。

親の初期化処理が完了した後は、target_tableの値を上書きしている。

これで、CustomETLの初期化処理は終了。次に、runメソッドが呼ばれる。

runメソッドの実行

runメソッド

runメソッドでは、3つの関数を実行している。

extractメソッドの実行

「[BaseETL] extract from /data/input.csv」をコンソールに出力している。

source_pathには、BaseETLで初期化した値が入っている。

transformメソッドの実行

次に、tranformメソッドが実行される。

ここで実行されるtransformメソッドは、BaseETLではなく、CuntomETLのメンバ関数。

コンソールに「[CustomETL] 独自の変換処理」と出力される。

loadメソッドの実行

最後に、loadメソッドが実行される。

CustomETLで何も手を加えていないので、BaseETLのloadメソッドがそのまま実行される。

そしてコンソールに「[BaseETL] load into custom_table」と出力される。

ここで注意が必要なのが、custom_tableという箇所。

BaseETLで定義したdefault_tableは、CustomETLで上書きされている。

そのため、default_tableではなく、custom_tableが出力されている。

本日の実務で深まった理解

「子クラスでコンストラクタに処理を追加したい。」「親クラスのコンストラクタの処理は引き継ぎたい」という場合、super().__init__()を使用する。

親クラスの内容をそのまま持ってきても構わなければ、コンストラクタを書く必要はない。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です