首页 > 解决方案 > 使用 namedtuple 的部分属性进行比较

问题描述

我有一个带有字段 (x, y, z) 的命名元组,其中 z 是可选的。

像“in”这样的比较运算符会考虑所有字段进行比较

from collections import namedtuple


p = namedtuple('p' , ('x' ,'y', 'z'), defaults = (None,) * 3)

a = p(1,2, 0)
b = p(2,1)

co_ord_list = [a,b]

c = p(1,2)
if c in co_ord_list :
    print(f"Already Exists")
else :
    co_ord_list.append(c)

print(co_ord_list)

当'c'匹配'x'并且'y'已经存在时,我不希望将'c'添加到列表中。

实际输出:[p(x=1, y=2, z=0), p(x=2, y=1, z=None), p(x=1, y=2, z=None)]

预期输出:已经存在

标签: python-3.xlistnamedtuple

解决方案


您可以通过扩展命名元组和覆盖方法很容易地做到这一点__eq__

class p(namedtuple('p' , ('x' ,'y', 'z'), defaults = (None,) * 3)):

    def __eq__(self, other):
        return isinstance(other, self.__class__) and self.x == other.x and self.y == other.y

    def __hash__(self):
        return hash((x, y))

a = p(1,2, 0)
b = p(2,1)

co_ord_list = [a,b]

c = p(1,2)
if c in co_ord_list :
    print(f"Already Exists")
else :
    co_ord_list.append(c)

print(co_ord_list)

输出:

Already Exists
[p(x=1, y=2, z=0), p(x=2, y=1, z=None)]

您的示例可以在不定义您自己的hash函数的情况下工作,但这是一个很好的做法,因为这a == b意味着hash(a) == hash(b). isinstance(other, self.__class__)如果没有方法中的条件,它也可以工作,__eq__但这可以防止AttributeError在比较不同类型的对象时发生这种情况,如果您的列表co_ord_list还包含其他类型的对象。


推荐阅读