使用 namedtuple 的部分属性进行比较

Use partial attributes from namedtuple for comparison

我有一个带字段 (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' 已经存在时被添加到列表中。

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

预期输出:已经存在

你可以很容易地通过扩展命名元组和覆盖方法来做到这一点 __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)。在 __eq__ 方法的条件下,它也可以在没有 isinstance(other, self.__class__) 的情况下工作,但这可以防止 AttributeError 在比较不同类型的对象时发生这种情况,如果你的列表 co_ord_list 也包含对象一些其他类型。