将两个列表与自定义对象进行比较,但表现不符合我的预期(词法比较)-Python

时间:2019-07-18 13:54:11

标签: python list comparison

我有两个Python列表。

a = [A(1), B(1)]
b = [A(1), B(2)]

支票a < b无法调用B的__lt__运算符。结论是 a 不小于 b 。 我已经验证了A的__lt__被调用(实际上是两次以查看 a 中的第一个元素是否小于 b 中的元素,然后以另一种方式周围。)

预先感谢

Oren

3 个答案:

答案 0 :(得分:2)

在Python中比较两个列表时,它将逐个元素地比较它们,并在找到两个不相等的元素后停止比较它们。这并不意味着一个元素必须大于或小于另一个,而不仅仅是它们不相等。这是一个幼稚的示例,使用了与您所拥有的东西相似的东西;考虑一个class A

class A:

    def __init__(self, val):
        self.val = val

    def __lt__(self, obj):
        return self.val < obj.val

现在考虑两个对象ab,使得a = A(1)b = A(1)a < b的取值为False,与我们期望的一样,但是a == b的取值为False。这是因为对象无法通过__eq__方法比较相等性,并且对象不是完全相同的实例。我们可以这样添加一个:

def __eq__(self, obj):
    return self.val == obj.val

现在,a == b的计算结果为True,您的原始表达式将按预期工作。

答案 1 :(得分:1)

只有在发现第一项相等时,Python才会比较第二项。如果不比较第二个项目,则意味着第一个项目不相等。

因此,问题可能出在A的__lt__实现上,如果您想发布该代码,我们也许可以帮助发现问题。

答案 2 :(得分:1)

the python documentation明确指出,在第一个不相等的对象上调用了 lt 。在您的示例中,您没有提到您添加了 eq 运算符,所以这是我的复制品:

class A:
    def __init__(self, val):
        self.val = val

    def __lt__(self, other):
        print('lt in A')
        return self.val < other.val

class B:
     def __init__(self, val):
         self.val = val
    def __lt__(self, other):
         print('lt in B')
         return self.val < other.val

a = [A(1), B(2)]
b = [A(1), B(1)]

print(a < b)

输出:

lt in A
False

因为第一个对象是不同的(尽管值相同),它将采用该 lt

的结果

当您实现__eq__方法时,它将继续这样做:     A类:         def init (self,val):             self.val = val

    def __lt__(self, other):
        print('lt in A')
        return self.val < other.val

    def __eq__(self, other):
        return self.val == other.val

将输出

lt in B
True

因为第一个元素使用 eq

评估为true