Python {Article092}

ようこそ「Python」へ...

PyScriptでオブジェクト指向プログラミングを学習する: Python Object Oriented Programming【13】

この記事ではPythonでオブジェクト指向プログラミングを学習する方法を解説しています。 オブジェクト指向プログラミングは、次の13のシリーズから構成されています。 第13回目では、Employeeクラスの演算子(+)、比較演算子(==)を多重定義(overloading)する方法を学習します。 たとえば、Employeeクラスの加算(+)の演算子を多重定義するとクラスのオブジェクトを加算するといったことが可能になります。 同様にEmployeeクラスの)比較演算子(==)を多重定義するとクラスのオブジェクトが等しいかどうか比較することが可能になります。

この記事ではMicrosoftのVisual Studio Codeを使用していますが、Jupyter NotebookなどのツールでもOKです。 ここで解説しているPythonのコードは「GO LIVE DEMO」から直接編集しながら会話形式で学習することができます。

説明文の左側に図の画像が表示されていますが縮小されています。 画像を拡大するにはマウスを画像上に移動してクリックします。 画像が拡大表示されます。拡大された画像を閉じるには右上の[X]をクリックします。 画像の任意の場所をクリックして閉じることもできます。
click image to zoom!
図A:
click image to zoom!
図B:
click image to zoom!
図C:
click image to zoom!
図D:


Employeeクラスの演算子(+)・比較演算子(==)を多重定義する

  1. Employeeクラスに「__add__()」、「__eq__()」メソッドを追加してオブジェクトを加算、比較できるようにする

    Visual Studio Code(VSC)を起動したら新規ファイルを作成して行1-26を入力(コピペ)します。 行2-18ではEmployeeクラスを定義しています。 ここではEmployeeクラスの各種メソットの引数にデータ型(first: str, salary: float)を指定しています。 さらにメソッドから返す戻り値のデータ型(-> None, -> str, -> bool)も指定しています。 このように引数、戻り値のデータ型を記述しておくと保守性が向上します。

    行3-9では「__init__()」メソッドを定義しています。 行11-12では「__str__()」メソッドを定義しています。

    行14-15では「__add__()」メソッドを追加してオブジェクトを加算できるようにしています。 たとえば、「akio + taro」のような演算子を実行したときは、 __add__()の引数「self」にはakioのオブジェクトが格納されます。 そして引数「other」にはtaroのオブジェクトが格納されます。

    行17-18では「__eq__()」メソッドを追加してオブジェクトが等しいかどうか比較できるようにしています。 たとえば、「if akio == taro」のような比較演算子を実行したときは、 __eq__()の引数「self」にはakioのオブジェクトが格納されます。 そして引数「other」にはtaroのオブジェクトが格納されます。

    行20-23ではEmployeeのインスタントを生成してオブジェクトの属性を表示しています。 行24-25ではEmployeeの2個のオブジェクト(akio/taro)の「salary」を加算して結果を表示しています。 行24で「akio + taro」が実行されるとEmployeeクラスの「__add__()」メソッドが呼び出されます。 そしてEmployeeオブジェクトの属性(salary)が加算されます。 _add__()の引数「self」には「akio」のオブジェクトが格納されています。 引数「other」には「taro」のオブジェクトが格納されています。

    行26ではEmployeeの2個のオブジェクト(akio/taro)の「salary」が等しいかどうかを比較しています。 「if akio == taro」が実行されるとEmployeeクラスの「__eq__()」メソッドが呼び出されます。 _eq__()の引数「self」には「akio」のオブジェクトが格納されています。 引数「other」には「taro」のオブジェクトが格納されています。
    # Python Object-Oriented Programming [13].py
    class Employee:
        def __init__(self, first: str, last: str, salary: float) -> None:
            self.first = first
            self.last = last
            try:
                self.salary = float(salary)
            except:
                raise ValueError(f"Invalid salary: {salary}")    
    
        def __str__(self) -> str:
            return f"Full Name: {self.first} {self.last}, Salary: US ${self.salary:,.2f}"
    
        def __add__(self, other) -> float:         
            return self.salary + other.salary
    
        def __eq__(self, other) -> bool:
            return self.salary == other.salary             
    
    akio = Employee('Akio', 'Kasai', 50_000.99)
    print(akio)
    taro = Employee('Taro', 'Yamada', 80_000.99)
    print(taro)
    total_salary = akio + taro
    print(f"Total salary: US ${total_salary:,.2f}")
    print('akio.salary == taro.salary' if akio == taro else 'akio.salary != taro.salary')

    click image to zoom!
    図1
    図1は実行結果です。 行21(図1)の「Employee()」が実行されるとEmployeeクラスの「__init__()」メソッドが呼び出されます。 行22(図1)の「print(akio)」が実行されるとEmployeeクラスの「__str__()」メソッドが呼び出されます。

    行25(図1)の「akio + taro」が実行されるとEmployeeクラスの「__add__()」メソッドが呼び出されます。 ここでは「akio.salary」と「taro.salary」を加算して合計を戻り値として返します。 行26ではSalaryの合計値を表示しています。

    行27(図1)の「if akio == taro」が実行されるとEmployeeクラスの「__eq__()」メソッドが呼び出されます。 ここでは「akio.salary」と「taro.salary」が等しいかどうかを比較して結果をbool型で返します。


  2. Live DEMO

    【Live DEMO】からPythonのコードを実行するには緑色の[▶]をクリックします。 PyScriptの場合、input()ステートメントを実行するとポップアップが表示されるのでテキストボックスに入力します。 なお「input('Enter first name: ')」のように記述してもメッセージは表示されないのでここでは省力しています。 [▶]をクリックすると「First name」のポップアップが表示されるので「名前」を入力して[OK}をクリックします。 すると「Last name」のポップアップが表示されるので「姓名」を入力して[OK]をクリックします。 Pythonのコードは編集してから実行することもできます。

    click image to zoom!
    図2-1
    図2-1は緑色の[▶]をクリックしてPythonのコードを実行した画面です。 ここでは行27(図2-1)の「akio + taro」の処理の流れを説明しています。 行27(図2-1)の「akio + taro」が実行されるとEmployeeクラスの「__add__()」メソッドが呼び出されます。 __add__()では「akio.salary」と「taro.salary」の金額を加算して合計値を返しています。 行28(図2-1)では合計金額を表示しています。 処理の流れは右側のトレース情報を参照してください。


    click image to zoom!
    図2-2
    図2-2では行23(図2-2)の「if akio == taro」の処理の流れを説明しています。 行23(図2-2)の「if akio == taro」が実行されるとEmployeeクラスの「__eq__()」メソッドが呼び出されます。 __eq__()では「akio.salary」と「tato.salary」が等しいかどうかを比較して結果をbool型で返しています。 akioとtaroの給料(salary)は異なるので「false」が返されます。 そしてブラウザには「akio.salary != taro.salary」が表示されます。 処理の流れは右側のトレース情報を参照してください。


Live DEMO