【问题标题】:comparing two list with custom objects, not behaving as I expect (Lexicography comparison) - Python将两个列表与自定义对象进行比较,行为不符合我的预期(词典比较)-Python
【发布时间】:2019-07-18 13:54:11
【问题描述】:

我有两个 Python 列表。

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

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

提前致谢,

奥伦

【问题讨论】:

  • 这是 python 2.7 还是 python 3.x ?
  • sys.version_info(major=3, minor=6, micro=4, releaselevel='final', serial=0)
  • 唯一困扰我的是你说它被调用了两次,这不应该发生,所以我认为这可能是调用代码中其他地方的问题。我的小型复制品没有双重通话问题
  • @miThom 你可能是对的,它只被称为一个。另一个调用来自我代码中的另一个来源。

标签: python list comparison


【解决方案1】:

当你在 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 &lt; b 计算结果为 False,正如我们所期望的那样,但 a == b 也计算结果为 False。这是因为对象无法通过__eq__ 方法比较相等性,并且对象不是完全相同的实例。我们可以像这样添加一个:

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

现在,a == b 将评估为 True,您的原始表达式将按预期工作。

【讨论】:

  • 知道了。谢谢,我也会实现__eq__
【解决方案2】:

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

所以问题可能在于 A 的 __lt__ 实现,如果您想发布该代码,我们或许可以帮助发现问题。

【讨论】:

  • 这并不完全正确,python 不会将第一个元素视为相同,因为它是不同的对象(不同的引用),这将导致 lt 在第一个对象只有一次
  • 这是“A”:class EMIDCandidate(Candidate): def __init__(self, keyword, count): super(EMIDCandidate, self).__init__(keyword) self.count = count def __repr__(self): return f"EMID: {self.keyword} x {self.count}" def __lt__(self, other): print("!", self, other) return self.count &lt; other.count
【解决方案3】:

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

因为第一个对象不同(尽管 val 相同),它会采用 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

求值为真

【讨论】:

    猜你喜欢
    • 2015-10-23
    • 2022-01-05
    • 2018-04-06
    • 2012-11-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-01
    • 1970-01-01
    相关资源
    最近更新 更多