Понимание членства объекта 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 эквивалентны, они не являются одним и тем же объектом, и это то, что тестируется.

Другие вопросы по тегам