Pythonで自作クラスの比較演算する方法(同値性比較の実装)

環境

  • Windows 10
  • Python 3.10.1
  • VSCode

この記事は何?

  • Pythonで作成した独自クラスは、デフォルトでは比較演算ができない
  • そのため、オブジェクト同士が同値であることを==等を用いて比較しようとしてもFalseになってしまい、テストの際などにちょっと悲しい

使用するソースコード

以下の公開リポジトリに置いています

GitHub - masayan1126/tao-py-py: pythonリポジトリ
pythonリポジトリ. Contribute to masayan1126/tao-py-py development by creating an account on GitHub.

なぜ自分で作成したクラスは比較できないのか

単にコンストラクタや、プロパティ、メソッドを定義しただけでは、足りず、以下のような特殊メソッドを定義する必要があるため

※厳密には、eqが定義されていれば、neはその反対なので、定義されていなくてもOK

メソッド名内容
__lt__Less Than:未満
__le__Less Than or Equal:以下
__eq__Equal:同じ
__ne__Not Equal:違う
__gt__Greater Than:より大きい
__ge__Greater Than or Equal:以上

めんどくさくない?

  • 毎回6つもメソッドを定義してられないので、Pythonではfunctoolsパッケージのtotal_orderingというでコレーターが存在しており、こちらを使用することで上記よりも簡潔に比較演算を定義することができます
  • functoolsのtotal_orderingというデコレータが、__eq__と__lt__の内容から、その他の比較メソッドを推測してくれるhttps://docs.python.org/ja/3/library/functools.html#functools.total_ordering
  • こちらを使用することにより、以下のように、__eq__と__lt__の2つだけでよくなります(ちなみに、以下はwebスクレイピングで取得したWebElementを管理する用の自作クラスです)

shared\Domain\xweb_element.py

from shared.Domain.i_xweb_element import IXWebElement
from selenium.webdriver.remote.webelement import WebElement
from functools import total_ordering

@total_ordering # デコレーター
class XWebElement(IXWebElement):
    def __init__(self, element: WebElement, value):
        self.element = element
        self.value = value
    def __eq__(self, other):
        if not isinstance(other, XWebElement):
            return NotImplemented
        return (self.element, self.value) == (other.element, self.value)

    def __lt__(self, other):
        if not isinstance(other, XWebElement):
            return NotImplemented
        return (self.element, self.value) < (other.element, self.value)

    def get_element(self):
        return self.element

    def get_value(self):
        return self.value

以上です

Python学習におすすめの書籍

独習Python/山田祥寛【3000円以上送料無料】
bookfan 1号店 楽天市場店
¥ 3,300(2022/02/05 17:20時点)
タイトルとURLをコピーしました