Python でクラスのオブジェクトを比較するには __lt__ と __eq__ を定義する - インスタンスに大小関係をつくる方法
2023.02.18
Python で独自に定義したクラスのオブジェクトを比較できるか実験します。
class City:
def __init__(self, name, population, crime):
self.name = name
self.population = population
self.crime = crime
adachi = City(name='足立区', population=690448, crime=3212)
bunkyo = City(name='文京区', population=229828, crime=808)
print(adachi < bunkyo)
# TypeError: '<' not supported between instances of 'City' and 'City'
City
インスタンスの比較はサポートされていないと警告がでました。ちなみにインスタンス変数は
population 2022 年 10 月における人口
crime 2021 年の犯罪数
を意味します。数値は
文京区人口統計資料
足立区の年齢別人口
区市町村の町丁別、罪種別及び手口別認知件数
から引用しました。
演算子を定義する
class City:
def __init__(self, name, population, crime):
self.name = name
self.population = population
self.crime = crime
def __lt__(self, other):
rate = self.crime / self.population * 100
other_rate = other.crime / other.population * 100
return rate < other_rate
adachi = City(name='足立区', population=690448, crime=3212)
bunkyo = City(name='文京区', population=229828, crime=808)
print(bunkyo < adachi) # True
クラスに __lt__
を定義すると <
が使えるようになります。__lt__
は自分と他人を引数とします。犯罪率で都市の大小関係を示すため、自分の犯罪率 rate
と他人の犯罪率 other_rate
を計算しました。
この関数は、自分の値が他人のそれより小さいときに True を返し、それ以外で False を返します。
反対の記号も定義される
__lt__
は <
を意味しますが、__lt__
を定義すると >
も使えるようになります。
print(adachi > bunkyo) # True
等号
上のままでは等号が不正確になります。
class City:
def __init__(self, name, population, crime):
self.name = name
self.population = population
self.crime = crime
def __lt__(self, other):
rate = self.crime / self.population * 100
other_rate = other.crime / other.population * 100
return rate < other_rate
bunkyo = City(name='文京区', population=229828, crime=808)
sample = City(name='', population=229828, crime=808)
print(bunkyo == sample) # False
人口と犯罪が同じ bunkyo と sample は犯罪率が等しく、bunkyo == sample
は本来 True です。そこで __eq__
を定義します。
class City:
def __init__(self, name, population, crime):
self.name = name
self.population = population
self.crime = crime
def __eq__(self, other):
rate = self.crime / self.population * 100
other_rate = other.crime / other.population * 100
return rate == other_rate
def __lt__(self, other):
rate = self.crime / self.population * 100
other_rate = other.crime / other.population * 100
return rate < other_rate
bunkyo = City(name='文京区', population=229828, crime=808)
sample = City(name='', population=229828, crime=808)
print(bunkyo == sample) # True
__eq__
はオブジェクトが等しいかどうかをチェックするさいに呼ばれます。こうしてオブジェクトの大小関係がおおむね定義されました。