Понимание членства объекта Python для множеств - PullRequest
5 голосов
/ 09 сентября 2010

Если я правильно понимаю, функция __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 ]

5 голосов
/ 09 сентября 2010

Добавление метода __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!
2 голосов
/ 09 сентября 2010
>>> 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 '__hash__, будутникогда не хэшируйте одно и то же значение (хорошо, если только адресное пространство не превышает sizeof хеша).

1 голос
/ 09 сентября 2010

Как отмечали другие, ваши объекты не имеют __hash__, поэтому они используют идентификатор по умолчанию в качестве хэша, и вы можете переопределить его, как предложил Натон, НО читать документы __hash__, особенно о том, когда вам следует и не следует делать это.

0 голосов
/ 09 сентября 2010

Набор использует закулисный закулис, поэтому оператор in проверяет, существует ли объект как ключ в dict. Поскольку ваш объект не реализует хеш-функцию, стандартная хеш-функция для объектов использует идентификатор объекта. Таким образом, хотя a и b эквивалентны, они не являются одним и тем же объектом, и это то, что проверяется.

...