Мне нужно создать объект или класс «контейнер» в Python, который будет вести учет других объектов, которые я также определяю. Одно из требований этого контейнера заключается в том, что если два объекта считаются идентичными, один (любой из них) удаляется. Моей первой мыслью было использовать в set([])
качестве содержащего объекта, чтобы выполнить это требование.
Однако набор не удаляет один из двух идентичных экземпляров объекта. Что я должен определить, чтобы создать его?
Вот код Python.
class Item(object):
def __init__(self, foo, bar):
self.foo = foo
self.bar = bar
def __repr__(self):
return "Item(%s, %s)" % (self.foo, self.bar)
def __eq__(self, other):
if isinstance(other, Item):
return ((self.foo == other.foo) and (self.bar == other.bar))
else:
return False
def __ne__(self, other):
return (not self.__eq__(other))
Переводчик
>>> set([Item(1,2), Item(1,2)])
set([Item(1, 2), Item(1, 2)])
Ясно, что __eq__()
, который вызывается x == y
, не является методом, вызываемым набором. Что вызвано? Какой еще метод я должен определить?
Примечание. Item
S должен оставаться изменяемым и может изменяться, поэтому я не могу предоставить __hash__()
метод. Если это единственный способ сделать это, я перепишу его для использования неизменяемых Item
s.
Ответы:
Боюсь, вам придется предоставить
__hash__()
метод. Но вы можете закодировать его так, чтобы он не зависел от изменяемых атрибутов вашегоItem
.источник
__hash__()
следует определять только для неизменяемых объектов.__eq__
? Сравнивая эти (1,2) атрибуты? Затем вы должны также вернуть некоторый хэш (1,2) в свой__hash__
метод.hash
встроенную команду:hash((self.foo, self.bar))
. При этом используется хэш кортежа, который подходит для ваших нужд. (Ваше__eq__
также можно было бы написать в терминахtuple
сравнения.)Да, вам нужен
__hash__()
-метод И оператор сравнения, который вы уже предоставили.class Item(object): def __init__(self, foo, bar): self.foo = foo self.bar = bar def __repr__(self): return "Item(%s, %s)" % (self.foo, self.bar) def __eq__(self, other): if isinstance(other, Item): return ((self.foo == other.foo) and (self.bar == other.bar)) else: return False def __ne__(self, other): return (not self.__eq__(other)) def __hash__(self): return hash(self.__repr__())
источник
__ne__
, и даже в 2.x вы не должны определять__ne__
в терминах__eq__
. Смотрите, stackoverflow.com/a/30676267/5337834