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

Python 如何从容器中移除相等的对象(但不一定是相同的对象)?,python,object,set,containers,Python,Object,Set,Containers,我想做一些类似的事情: 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):

我想做一些类似的事情:

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.index
是否与
self.mySet
中的任何
cell.index
匹配。是否有我可以为此重写的
\uuu cmp\uuu
类型方法?或者我被迫循环遍历集合,每次检查索引,然后手动删除相应的条目?

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

如果类没有定义
\uuuu cmp\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu;如果它定义了
\uu cmp\uu()
\uu eq\uuu()
而不是
\uuu hash\uuu()
,则其实例将无法在哈希集合中使用。如果类定义了可变对象并实现了
\uuu cmp\uuu()
\uuu eq\uuuu()
方法,那么它不应该实现
\uu hash\uuuu()
,因为可哈希集合实现要求对象的哈希值是不可变的(如果对象的哈希值发生变化,它将位于错误的哈希桶中)

默认情况下,用户定义的类具有
\uuu cmp\uu()
\uu hash\uuu()
方法;使用它们,所有对象比较不相等(除了它们自己)和
x.\uuuu hash\uuuu()
返回从
id(x)
派生的结果

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

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)
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))
由于您希望基于
索引
进行比较,因此只有
索引
会被散列并在重写的
\uuuuuuuuuuuuu散列
方法中返回

如果两个散列值相等,Python将通过内部调用
\uuuuueq\uuu
方法来检查这两个对象是否相同。因此,我们也重写了该方法,只返回比较两个对象的
index
的结果

    def __eq__(self, other):
        return other.index == self.index
我们已经覆盖了
\uuu repr\uu
,只是为了在打印时查看实际的元素

现在,当你这样做的时候

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)
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])

注意,我们试图删除的<代码>单元< /代码>对象的值为<代码> 99 >代码>,因为我们只考虑了“代码>索引/代码>对象标识,它用索引<代码>(0, 1)< /C> >删除<代码>单元< /代码> .< /p>该CaseS的集合是什么?您尝试重写<代码>(在Cell类上)@user2357112--hm,这正是我在@MrDuk上发现的:正如页面顶部所说,该模块已被弃用

set
(带小写s)现在是一种内置类型。也许您可以使用字典
{cell.index:cell}
而不是集合。