如何从容器中移除相同的对象(但不一定是同一个对象)?
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)
.
我想做类似的事情:
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) andx.__hash__()
returns a result derived fromid(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)
.