Понимание членства объекта Python для множеств
Если я правильно понимаю, функция __cmp__() объекта вызывается для оценки всех объектов в коллекции при определении, является ли объект членом или "в" коллекции. Тем не менее, это не относится к сетам:
class MyObject(object):
def __init__(self, data):
self.data = data
def __cmp__(self, other):
return self.data-other.data
a = MyObject(5)
b = MyObject(5)
print a in [b] //evaluates to True, as I'd expect
print a in set([b]) //evaluates to False
Как проверяется членство объекта в наборе?
4 ответа
>>> xs = []
>>> set([xs])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'
Вот ты где. Наборы используют хэши, очень похожие на dicts. Это значительно повышает производительность (тесты на членство - O(1), а многие другие операции зависят от тестов на членство), а также хорошо соответствуют семантике наборов: элементы набора должны быть уникальными, и разные элементы будут создавать разные хэши, в то время как одни и те же хэши указать (ну в теории) дубликаты.
Так как по умолчанию __hash__
просто id
(что довольно глупо imho), два экземпляра класса, который наследует object
"s __hash__
никогда не будет хэшировать одно и то же значение (ну, если только адресное пространство не превышает sizeof
хэш).
Добавление __hash__
Метод вашего класса дает это:
class MyObject(object):
def __init__(self, data):
self.data = data
def __cmp__(self, other):
return self.data - other.data
def __hash__(self):
return hash(self.data)
a = MyObject(5)
b = MyObject(5)
print a in [b] # True
print a in set([b]) # Also True!
Как указывали другие, ваши объекты не имеют __hash__
поэтому они используют идентификатор по умолчанию в качестве хэша, и вы можете переопределить его, как предложил Натон, НО читать документы о__hash__
конкретно о том, когда вам следует и не следует делать это.
Набор использует закулисный закулис, поэтому оператор "in" проверяет, существует ли объект как ключ в диктовке. Поскольку ваш объект не реализует хеш-функцию, стандартная хеш-функция для объектов использует идентификатор объекта. Таким образом, хотя a и b эквивалентны, они не являются одним и тем же объектом, и это то, что тестируется.