Python クラスの等価性

Aditya Raj 2023年6月21日
  1. Python でのクラス オブジェクトの等価性
  2. __eq__() メソッドを使用した Python クラスの等価性
  3. id() メソッドを使用した Python クラスの等価性
Python クラスの等価性

Python では、比較演算子を使用してさまざまなデータ型を比較できます。 ただし、カスタム クラスを作成するときに比較演算子を使用してそれらを単純に比較することはできません。

この記事では、Python でカスタム クラスを使用して定義されたオブジェクトの等価性をチェックするさまざまな方法について説明します。

Python でのクラス オブジェクトの等価性

整数や文字列などの組み込みオブジェクトがある場合、以下に示すように、== 演算子を使用してそれらが等しいかどうかを簡単に確認できます。

num1 = 12
num2 = 10
result = num1 == num2
print("{} and {} are equal:{}".format(num1, num2, result))

出力:

12 and 10 are equal:False

ここで、値 12 と 10 は整数であるため、== 演算子は出力として正しい値を与えます。 ただし、カスタム クラスのオブジェクトがある場合、Python インタープリターの動作は異なります。

たとえば、以下に示すように、length という 1つの属性のみを持つ Length クラスがあるとします。

class Length:
    def __init__(self, value):
        self.length = value

length 属性に同じ値を持つクラス Length の 2つのインスタンスを作成します。

class Length:
    def __init__(self, value):
        self.length = value


len1 = Length(10)
len2 = Length(10)

== 演算子を使用してオブジェクトを比較すると、両方のインスタンスの length 属性が同じ値であっても、結果は False になります。 これは、次のコードで確認できます。

class Length:
    def __init__(self, value):
        self.length = value


len1 = Length(10)
len2 = Length(10)
result = len1 == len2
print("len1 and len2 are equal:", result)

出力:

len1 and len2 are equal: False

上記の Python インタープリターの動作は、ユーザー定義クラスの 2つのオブジェクトを比較する方法を使用して説明できます。 Python で == 演算子を使用して 2つのクラス オブジェクトの等価性をチェックすると、両方のオブジェクトが同じメモリ位置を参照している場合にのみ、結果は True になります。

つまり、2つの変数がありますが、Python オブジェクトは 1つだけです。 これは、次の例で確認できます。

class Length:
    def __init__(self, value):
        self.length = value


len1 = Length(10)
len2 = len1
result = len1 == len2
print("len1 and len2 are equal:", result)

出力:

len1 and len2 are equal: True

両方の変数がユーザー定義クラスの同じインスタンスを参照している場合にのみ、等値演算子が True を返すことを理解しているかもしれません。

Python でクラスの異なるインスタンスの等価性をチェックする必要がある場合はどうすればよいですか? 調べてみましょう。

__eq__() メソッドを使用した Python クラスの等価性

__eq__() メソッドをオーバーライドすることで、== 演算子がカスタム クラスでどのように機能するかを変更できます。 たとえば、Length クラスの 2つのインスタンスの長さをチェックするには、__eq__() メソッドをオーバーライドできます。

以下で説明する手順を __eq__() メソッド内で使用します。

  1. Length クラスのインスタンスで呼び出されると、__eq__() メソッドは、入力引数として別のオブジェクトを取ります。

  2. __eq__() メソッド内で、まず、入力オブジェクトが Length クラスのインスタンスであるかどうかを確認します。 これには、isinstance() 関数を使用できます。

  3. isinstance() 関数は、Python オブジェクトを最初の入力引数として取り、クラス名を 2 番目の入力引数として取ります。 実行後、オブジェクトが入力引数で提供されたクラスのインスタンスである場合、True を返します。

  4. Length クラスをプログラムの 2 番目の入力引数として渡します。 最初の引数で渡されたオブジェクトが Length クラスのインスタンスでない場合、False を返します。

    それ以外の場合は、先に進みます。

  5. 2つのオブジェクトのクラスが等しいかどうかを確認するために、両方のオブジェクトの属性 length の値を比較します。 値が等しい場合、True を返します。

    それ以外の場合は、False を返します。

__eq__() メソッドが Length クラスに実装されると、== 演算子を使用して Number クラスの 2つのインスタンスを正しく比較できます。

Length クラスの 2つのインスタンス、たとえば len1len2 があるとします。 len1==len2 を実行すると、len1.__eq__(len2) メソッドが実行されます。

同様に、len2==len1 を実行すると、len2.__eq__(len1) メソッドが実行されます。

コードの実行後、両方のオブジェクトの長さの値が同じ場合、len1==len2True を返します。 それ以外の場合、False を返します。

これは、次の例で確認できます。

class Length:
    def __init__(self, value):
        self.length = value

    def __eq__(self, other):
        isLength = isinstance(other, self.__class__)
        if not isLength:
            return False
        if self.length == other.length:
            return True
        else:
            return False


len1 = Length(10)
len2 = Length(10)
result = len1 == len2
print("len1 and len2 are equal:", result)

出力:

len1 and len2 are equal: True

id() メソッドを使用した Python クラスの等価性

また、カスタム クラスのオブジェクトを持つ 2つの変数が同じオブジェクトを参照しているかどうかを確認することもできます。 これには、id() 関数を使用できます。

id() 関数は、オブジェクトを入力引数として取り、任意のメモリ位置で一意の ID 番号を返します。 これは、次の例で確認できます。

class Length:
    def __init__(self, value):
        self.length = value

    def __eq__(self, other):
        isLength = isinstance(other, self.__class__)
        if not isLength:
            return False
        if self.length == other.length:
            return True
        else:
            return False


len1 = Length(10)
len2 = Length(10)
result1 = id(len1)
result2 = id(len2)
print("ID of len1 is ", result1)
print("ID of len2 is ", result2)

出力:

ID of len1 is  140057455513712
ID of len2 is  140057454483488

2つのオブジェクトが同じメモリ位置を参照する場合、id() 関数は両方のオブジェクトに対して同じ出力を返します。 id() 関数の出力を比較することで、オブジェクトが同じメモリ位置を参照しているかどうかを確認できます。

これは、次の例で確認できます。

class Length:
    def __init__(self, value):
        self.length = value

    def __eq__(self, other):
        isLength = isinstance(other, self.__class__)
        if not isLength:
            return False
        if self.length == other.length:
            return True
        else:
            return False


len1 = Length(10)
len2 = Length(10)
result1 = id(len1)
result2 = id(len2)
result = result1 == result2
print("len1 and len2 are equal:", result)

出力:

len1 and len2 are equal: False

ここでは、オブジェクトの属性の値をチェックして、クラスが等しいかどうかをチェックしていないことがわかります。

この場合、オブジェクトが同じメモリ位置を参照しているかどうかのみをチェックしています。 したがって、Python クラスの等価性をチェックするこのアプローチは、クラス定義で __eq__() メソッドを実装せずに == 演算子を使用するのと同じです。

著者: Aditya Raj
Aditya Raj avatar Aditya Raj avatar

Aditya Raj is a highly skilled technical professional with a background in IT and business, holding an Integrated B.Tech (IT) and MBA (IT) from the Indian Institute of Information Technology Allahabad. With a solid foundation in data analytics, programming languages (C, Java, Python), and software environments, Aditya has excelled in various roles. He has significant experience as a Technical Content Writer for Python on multiple platforms and has interned in data analytics at Apollo Clinics. His projects demonstrate a keen interest in cutting-edge technology and problem-solving, showcasing his proficiency in areas like data mining and software development. Aditya's achievements include securing a top position in a project demonstration competition and gaining certifications in Python, SQL, and digital marketing fundamentals.

GitHub

関連記事 - Python Class