如何从容器中移除相同的对象(但不一定是同一个对象)?

How can you remove equal objects from containers (but not necessarily the same object)?

我想做类似的事情:

class Thing(object):
    self.mySet = Set()
    self.mySet.add(Cell((0,0),25))
    self.mySet.add(Cell((0,1),50))
    self.mySet.add(Cell((0,2),75))

    def ClaimCell(self, cell):
        self.mySet.remove(cell)

class Cell(object):
    def __init__(self,index,value):
        self.index = index
        self.value = value

但本质上,我希望能够根据 Cell 的成员而不是实例本身进行查找。我希望能够测试传入的 cell.index 是否与 self.mySet 中的任何 cell.index 匹配。有没有我可以为此覆盖的 __cmp__ 类型方法?还是我被迫循环遍历 Set,每次检查索引,然后手动删除相应的条目?

在Python中,相似的两个对象并不相同。引用 __hash__,

的文档

If a class does not define a __cmp__() or __eq__() method it should not define a __hash__() operation either; if it defines __cmp__() or __eq__() but not __hash__(), its instances will not be usable in hashed collections. If a class defines mutable objects and implements a __cmp__() or __eq__() method, it should not implement __hash__(), since hashable collection implementations require that a object’s hash value is immutable (if the object’s hash value changes, it will be in the wrong hash bucket).

User-defined classes have __cmp__() and __hash__() methods by default; with them, all objects compare unequal (except with themselves) and x.__hash__() returns a result derived from id(x).

因此,如果您想将两个对象视为相同的对象,则需要重写 __eq____hash__ 方法,如下所示

class Cell(object):

    def __init__(self, index, value):
        self.index = index
        self.value = value

    def __hash__(self):
        return hash(self.index)

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

    def __repr__(self):
        return "Index: {}, Value: {}".format(self.index, self.value)

由于您想基于 index 进行比较,因此只有 index 被散列并在重写的 __hash__ 方法中被 returned。

如果两个散列值相等,那么Python将通过内部调用__eq__方法检查两个对象是否相同。因此,我们也覆盖了该方法,return 只是比较两个对象的 index 的结果,

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

我们已经覆盖 __repr__ 只是为了在打印时查看实际元素。

现在,当你做这样的事情时

class Thing(object):

    def __init__(self):
        self.mySet = set()
        self.mySet.add(Cell((0, 0), 25))
        self.mySet.add(Cell((0, 1), 50))
        self.mySet.add(Cell((0, 2), 75))

    def ClaimCell(self, cell):
        self.mySet.remove(cell)
        print(self.mySet)

Thing().ClaimCell(Cell((0, 1), 99))

你会得到

set([Index: (0, 0), Value: 25, Index: (0, 2), Value: 75])

请注意,我们要删除的 Cell 对象的值为 99,因为我们只考虑 index 对象标识,它会删除 Cell 索引 (0, 1).