工業製造
産業用モノのインターネット | 工業材料 | 機器のメンテナンスと修理 | 産業プログラミング |
home  MfgRobots >> 工業製造 >  >> Industrial programming >> Python

Python演算子オーバーロード完全ガイド:__add__、__lt__など特殊メソッドでOOP設計を強化

Python演算子オーバーロード

Pythonの組み込み演算子はオペランド型によって異なる振る舞いをします。+演算子は数値加算、文字列連結、リスト結合など多様です。この柔軟性は演算子オーバーロードによって実現されており、自作クラスに文脈依存の意味を演算子に割り当てられます。

2次元平面上の座標を表すシンプルなPointクラスを考えます。特殊メソッドなしで2点加算を試みるとTypeErrorが発生します:

class Point:
    def __init__(self, x=0, y=0):
        self.x = x
        self.y = y
p1 = Point(1, 2)
p2 = Point(2, 3)
print(p1+p2)

出力

Traceback (most recent call last): File "<string>", line 9, in <module> print(p1+p2) TypeError: unsupported operand type(s) for +: 'Point' and 'Point'

Pythonには2つのPointインスタンスをどう結合するか組み込み知識がないため例外を投げます。演算子オーバーロードでこの振る舞いを自前定義できます。

Python特殊メソッド

ダブルアンダースコアで囲まれたメソッド—__init__、__str__、__add__など—は特殊メソッドまたは「ダンダー」メソッドと呼ばれます。これらはPythonランタイムによって暗黙的に呼び出され、演算子オーバーロード、コンテナプロトコルなどのフックポイントとなります。

例えば__str__メソッドはオブジェクトが人間可読文字列に変換される方法を制御します。デフォルトではオブジェクト出力はメモリアドレス表示であまり有用ではありません。__str__をオーバーライドするとデバッグとログが格段に明確になります:

class Point:
    def __init__(self, x=0, y=0):
        self.x = x
        self.y = y
    def __str__(self):
        return '({0}, {1})'.format(self.x, self.y)

これでPointを出力すると:

p1 = Point(2, 3)
print(p1)

出力

(2, 3)

同じ表現がstr(p1)とformat(p1)でも使用されます。Pythonは内部的にp1.__str__()を呼び出すためです。

+演算子のオーバーロード

Pointオブジェクトの加算をカスタマイズするには__add__を実装:

class Point:
    def __init__(self, x=0, y=0):
        self.x = x
        self.y = y
    def __str__(self):
        return '({0}, {1})'.format(self.x, self.y)
    def __add__(self, other):
        return Point(self.x + other.x, self.y + other.y)

新しい振る舞いをテスト:

p1 = Point(1, 2)
p2 = Point(2, 3)
print(p1 + p2)

出力

(3, 5)

裏ではPythonがp1.__add__(p2)を実行し、座標和を持つ新しいPointを返します。

他の算術演算子と実装すべき特殊メソッドのクイックリファレンス:

演算子式特殊メソッド
加算p1 + p2__add__(self, other)
減算p1 - p2__sub__(self, other)
乗算p1 * p2__mul__(self, other)
累乗p1 ** p2__pow__(self, other)
除算p1 / p2__truediv__(self, other)
切り捨て除算p1 // p2__floordiv__(self, other)
剰余p1 % p2__mod__(self, other)
左シフトp1 << p2__lshift__(self, other)
右シフトp1 >> p2__rshift__(self, other)
ビットANDp1 & p2__and__(self, other)
ビットORp1 | p2__or__(self, other)
ビットXORp1 ^ p2__xor__(self, other)
ビットNOT~p1__invert__(self)

比較演算子のオーバーロード

演算子オーバーロードは算術に限られません。比較演算子もカスタマイズ可能。例えば原点からの距離で点を比較するには__lt__をオーバーライド:

class Point:
    def __init__(self, x=0, y=0):
        self.x = x
        self.y = y
    def __str__(self):
        return '({0}, {1})'.format(self.x, self.y)
    def __lt__(self, other):
        self_mag = self.x**2 + self.y**2
        other_mag = other.x**2 + other.y**2
        return self_mag < other_mag

使用例:

p1 = Point(1, 1)
p2 = Point(-2, -3)
p3 = Point(1, -1)
print(p1 < p2)  # True
print(p2 < p3)  # False
print(p1 < p3)  # False

他の比較メソッドも同様のパターン:

演算子式特殊メソッド
未満p1 < p2__lt__(self, other)
以下p1 <= p2__le__(self, other)
等価p1 == p2__eq__(self, other)
非等価p1 != p2__ne__(self, other)
超過p1 > p2__gt__(self, other)
以上p1 >= p2__ge__(self, other)

これらメソッドを慎重に定義することで、カスタムオブジェクトを算術・比較コンテキストで自然に参加させ、コードの可読性と保守性を向上できます。

Python

  1. Python データ型マスター: 実践ガイド
  2. Python 演算子完全マスター: 包括的ガイド
  3. Python pass文完全マスター: 実践ガイド
  4. Python 関数引数完全マスター: 位置引数・キーワード引数・デフォルト引数
  5. Python辞書完全ガイド:作成、操作、高度なテクニック
  6. Python継承マスター:概念、構文、実践例
  7. Pythonイテレータ完全ガイド:仕組みと自作方法
  8. Pythonクロージャ解説:ネスト関数が変数を捕捉する仕組み
  9. Python @propertyデコレータマスター:クリーンで後方互換なゲッター/セッター
  10. Python datetimeマスター:日付・時刻・タイムゾーン実践ガイド
  11. Pythonのtime.sleep()をマスター:ベストプラクティス、マルチスレッド、実例