【Python】演算子のオーバーロード【特殊メソッドの使い方】

Python

この記事では、Pythonで演算子のオーバーロードをする方法を解説します。

組み込み型では、+で演算ができたり、==で比較ができたりします。演算子のオーバーロードを行うことで、ユーザー定義型でも同じような振る舞いを持たせることができます。

つまり、演算子のオーバーロードとは、ユーザー定義型で演算や比較を行えるようにするための機能です。

演算子をオーバーロードするにはクラスに特殊メソッドを定義します。
それでは特殊メソッドの使い方を見ていきましょう!

比較演算子の特殊メソッド

比較演算子用の特殊メソッドを定義することで、ユーザー定義型で比較を行えるようにできます。

比較演算子の特殊メソッド一覧

演算子機能特殊メソッド
<小なり__lt__(self, other)
<=小なりイコール__le__(self, other)
>大なり__gt__(self, other)
>=大なりイコール__ge__(self, other)
==等しい__eq__(self, other)
!=等しくない__ne__(self, other)

サンプル

試しに「==」で等しいか判定できるクラスを定義します。特殊メソッドのother引数には、比較対象のオブジェクトが渡されます。

class Num:
    def __init__(self, num):
        self.num = num
    
    # 特殊メソッド
    def __eq__(self, other):
        # 同じクラスかどうかの判定
        if type(other) == Num: 
            return self.num == other.num
        raise TypeError()

# インスタンス化
zero1 = Num(0)
one = Num(1)
zero2 = Num(0)

print(f'zero1 == one: {zero1 == one}')
print(f'zero1 == zero2: {zero1 == zero2}')

実行結果

zero1 == one: False
zero1 == zero2: True

他の特殊メソッドも同じ要領で実装できます。

算術演算子(左辺)の特殊メソッド

算術演算子(左辺)の特殊メソッドを見ていきましょう。

ここで紹介する特殊メソッドは、計算時に自身が左辺の場合に呼び出されます。 A + B の時はAが左辺でBが右辺となります。

算術演算子(左辺)の特殊メソッド一覧

演算子機能特殊メソッド
+足し算__add__(self, other)
引き算__sub__(self, other)
*掛け算__mul__(self, other)
/割り算__truediv__(self, other)
//切り捨て割り算__floordiv__(self, other)
%剰余(余り)__mod__(self, other)
**べき乗__pow__(self, other)

サンプル

試しに「+」で足し算ができるクラスを定義してみます。

class Num:
    def __init__(self, num):
        self.num = num
    
    # 特殊メソッド
    def __add__(self, other):
        # 同じクラスかどうかの判定
        if type(other) == Num: 
            return self.num + other.num
        raise TypeError()

# インスタンス化
one = Num(1)
two = Num(2)

print(f'one + two = {one + two}')

実行結果

one + two = 3

算術演算子(右辺)の特殊メソッド

計算時に自身が右辺の場合に呼び出される特殊メソッドです。
特殊メソッドが左辺と右辺のどちらも定義されている場合は、左辺の特殊メソッドが優先されます。

左辺に置くとエラーが発生するので気をつけましょう。

算術演算子(右辺)の特殊メソッド一覧

演算子機能特殊メソッド
+足し算__radd__(self, other)
引き算__rsub__(self, other)
*掛け算__rmul__(self, other)
/割り算__rtruediv__(self, other)
//切り捨て割り算__rfloordiv__(self, other)
%剰余(余り)__rmod__(self, other)
**べき乗__rpow__(self, other)

サンプル

試しに「+」で足し算ができるクラスを定義します。しかし、先ほどの特殊メソッドと違い左辺に置くことはできません。

class Num:
    def __init__(self, num):
        self.num = num
    
    # 特殊メソッド
    def __radd__(self, other):
        if type(other) == int:
            return self.num + other

# インスタンス化
one = Num(1)

print(f'2 + one = {2 + one}')

# 以下のように左辺に置くとエラー
one + 2

実行結果

2 + one = 3

算術代入演算子の特殊メソッド

代入演算子を実装するための特殊メソッドも用意されています。

算術代入演算子の特殊メソッド一覧

機能特殊メソッド
+=__iadd__(self, other)
-=__isub__(self, other)
*=__imul__(self, other)
/=__itruediv__(self, other)
//=__ifloordiv__(self, other)
%=__imod__(self, other)
**=__ipow__(self, other)

サンプル

例として「+=」で代入演算できるクラスを定義します。

class Num:
    def __init__(self, num):
        self.num = num
    
    # 特殊メソッド
    def __iadd__(self, other):
        if type(other) == Num:
            self.num +=  other.num
            return self

# インスタンス化
one = Num(1)
two = Num(2)

# 計算
one += two

print(f'one += two = {one.num}')

実行結果

one += two = 3

単項演算子の特殊メソッド

単項演算子も実装することができます。

単項演算子の特殊メソッド一覧

機能特殊メソッド
+instance__pos__(self)
-instance__neg__(self)
~instance__invert__(self)

サンプル

試しに「+instance」でインクリメントできるクラスを定義します。

class Num:
    def __init__(self, num):
        self.num = num
    
    # 特殊メソッド
    def __pos__(self, ):
        self.num += 1
        return self.num

# インスタンス化
zero = Num(0)

# 単項演算
+zero

print(f'zero.num = {zero.num}')
print(f'zero.num = {+zero}')

実行結果

zero.num = 1
zero.num = 2

まとめ

この記事では、Pythonの演算子のオーバーロードをする方法を解説しました。

演算子のオーバーロードを実装することで、組み込み型に似たユーザー定義型を作成することができます。比較や演算をよく行うクラスでは、オーバーロードしておくと便利です。

それでは今回の内容はここまでです。ではまたどこかで〜( ・∀・)ノ

タイトルとURLをコピーしました