programing

`__eq__`를 정의하는 유형은 해시 할 수 없습니까?

nasanasas 2020. 11. 21. 11:19
반응형

`__eq__`를 정의하는 유형은 해시 할 수 없습니까?


내 프로그램의 Python 3.1 포크로 기능을 이식 할 때 이상한 버그가있었습니다. 나는 그것을 다음 가설로 좁혔다.

Python 2.x와 달리 Python 3.x에서는 객체에 __eq__메서드가 있으면 자동으로 해시 할 수 없습니다.

이것이 사실입니까?

Python 3.1에서 일어나는 일은 다음과 같습니다.

>>> class O(object):
...     def __eq__(self, other):
...         return 'whatever'
...
>>> o = O()
>>> d = {o: 0}
Traceback (most recent call last):
  File "<pyshell#16>", line 1, in <module>
    d = {o: 0}
TypeError: unhashable type: 'O'

후속 질문은 개인 문제를 어떻게 해결합니까? 나는 과거의 특정 시점에 피클 덤프의 값을 각각 제공하는 여러 개체를 가리키는를 ChangeTracker저장 하는 개체 가 있습니다 WeakKeyDictionary. 기존 개체가 체크인 될 때마다 변경 추적기는 새 피클이 이전 피클과 동일한 지 여부를 알려주므로 그 동안 개체가 변경되었는지 여부를 알려줍니다. 문제는 이제 주어진 객체가 라이브러리에 있는지 확인할 수 없다는 것입니다. 객체가 해시 불가능하다는 예외를 발생시키기 때문입니다. (왜냐하면 __eq__방법 이 있기 때문 입니다.)이 문제를 어떻게 해결할 수 있습니까?


예, 정의 __eq__하면 기본값 __hash__(즉, 메모리에서 객체의 주소를 해싱)이 사라집니다. 이것은 해싱이 동일성과 일치해야하기 때문에 중요합니다. 동일한 객체는 동일하게 해시해야합니다.

해결책은 간단합니다. 정의 __hash__와 함께 정의하기 만하면 __eq__됩니다.


http://docs.python.org/3.1/reference/datamodel.html#object 의이 단락 . 해시시

재정의하는 클래스가 부모 클래스 __eq__()의 구현을 유지 __hash__()해야하는 경우 인터프리터는를 설정하여이를 명시 적으로 알려야합니다 __hash__ = <ParentClass>.__hash__. 그렇지 않으면 명시 적으로 None으로 설정 한 __hash__()것처럼 상속 이 차단됩니다 __hash__.


다음에서 Python 3 설명서를 확인하십시오 object.__hash__.

클래스가 __eq__()메서드를 정의하지 않으면 __hash__()작업도 정의해서는 안됩니다 . 정의 __eq__()하지만 그렇지 않은 __hash__()경우 해당 인스턴스는 해시 가능한 컬렉션의 항목으로 사용할 수 없습니다.

강조는 내 것입니다.

게으르고 싶다면 __hash__(self)return을 정의 할 수 있습니다 id(self).

사용자 정의 클래스에는 기본적으로 __eq__()__hash__()메서드가 있습니다. 그들과 함께, 모든 객체는 불평등을 비교하고 (자신을 제외하고)를 x.__hash__()반환합니다 id(x).


저는 파이썬 전문가는 아니지만 eq-method를 정의 할 때 해시 방법도 정의해야한다는 것이 말이되지 않을 것입니다 (객체의 해시 값을 계산 함) 그렇지 않으면 해싱 메커니즘 동일한 객체에 도달했는지 또는 동일한 해시 값을 가진 다른 객체에 도달했는지 알 수 없습니다. 실제로는 그 반대입니다. 아마도 당신의 __eq__방법에 의해 동일하다고 간주되는 객체에 대해 다른 해시 값을 계산하게 될 것 입니다.

나는 그 해시 함수가 무엇인지 __hash__모르겠다. :)

참고 URL : https://stackoverflow.com/questions/1608842/types-that-define-eq-are-unhashable

반응형