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 类,只有一个属性,length ,如下图所示。

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

我们将创建两个类Length 的实例,其length 属性的值相同。

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

如果你用== 操作符来比较这两个对象,结果将是False ,尽管这两个实例的length 属性的值都是一样的。你可以在下面的代码中观察到这一点。

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 解释器的上述行为可以用它比较两个用户定义的类的对象的方式来描述。当我们在Python中使用== 操作符检查两个类对象是否相等时,只有当两个对象都指向相同的内存位置时,结果才会是True

换句话说,会有两个变量,但只有一个 Python 对象。你可以在下面的例子中观察到这一点。

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 类的两个实例的长度,我们可以覆盖__eq__() 方法。

我们将使用下面在__eq__() 方法中讨论的步骤。

  1. __eq__() 方法,当对Length 类的一个实例进行调用时,将接受另一个对象作为其输入参数。

  2. __eq__() 方法中,我们将首先检查输入对象是否是Length 类的一个实例。为此,我们可以使用isinstance() 函数。

  3. isinstance() 函数将一个 Python 对象作为它的第一个输入参数,将类名作为它的第二个输入参数。执行后,如果该对象是输入参数中提供的类的实例,则返回True

  4. 在我们的程序中,我们将把Length 类作为第二个输入参数。如果第一个参数中传递的对象不是Length 类的实例,它将返回False

    否则,我们将继续前进。

  5. 为了检查两个对象的类是否相等,我们将比较两个对象中的属性length 的值。如果数值相等,我们将返回True

    否则,我们将返回False

一旦在Length 类中实现了__eq__() 方法,我们就可以使用== 操作符正确比较Number 类的两个实例。

假设我们有两个Length 类的实例,比如len1len2 。当我们执行len1==len2len1.__eq__(len2) 方法将被执行。

同样地,当我们执行len2==len1len2.__eq__(len1) 方法将被执行。

执行代码后,如果两个对象的长度值相同,len1==len2 将返回True 。否则,它将返回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类平等性

你也可以检查两个具有自定义类对象的变量是否指向同一个对象。为此,你可以使用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

如果两个对象指向相同的内存位置,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__() 方法。