Как тестирование членства отличается для списка и набора?

мне трудно понять, почему первое из этих утверждений в порядке, а второе вызывает ошибку.

subject_list = [Subject("A"), Subject("B"), Subject("C")]
subject_set = set()
subject_set.add(Subject("A"))
subject_set.add(Subject("B"))
subject_set.add(Subject("C"))

self.assertIn(Subject("A"), subject_list)
self.assertIn(Subject("A"), subject_set)

здесь ошибка:

Traceback (most recent call last):
  File "C:Users...testSubject.py", line 34, in testIn
    self.assertIn(Subject("A"), subject_set)
AssertionError: <Subject: A> not found in set([<Subject: B>, <Subject: C>, <Subject: A>])

тест на равенство в классе предмета просто self.name == other.name, и в другом UnitTest я проверяю, что Subject("A") == Subject("A") . Я действительно не могу понять, почему тему в списке, а не в наборе. В идеале я хотел бы, чтобы тема была в обоих.

4 ответов


выражение

Subject("A") in subject_list

сравнить Subject("A") к каждой записи в subject_list С помощью Subject.__eq__() метод. Если этот метод не перезаписан, по умолчанию он всегда возвращает False если только два операнда не являются тот же объект. Вышеприведенное выражение всегда будет возвращать False если Subject не хватает __eq__() метод, так как Subject("A") - это новый экземпляр, который уже не может быть в списке.

выражение

Subject("A") in subject_set

на наоборот будет использовать Subject.__hash__() сначала найдите нужное ведро и используйте Subject.__eq__() только после этого. Если вы не определили Subject.__hash__() в соответствии с Subject.__eq__(), это не удастся.


членство в наборе также зависит от хэша объекта, и поэтому вы должны реализовать __hash__() метод в классе соответствующим образом.


либо у вас нет __hash__() метод Subject класс, или это хитроумный. Попробуйте это:

def __hash__(self):
    return hash(self.name)

документы здесь.


чтобы использовать их в наборе, вы должны убедиться Subject правильно hashable. Если вы не определяете __hash__ себя, он просто возьмет id, и это отличается для разных экземпляров. __hash__ должно быть определено таким, что равные объекты имеют одинаковый хэш.