IT박스

파이썬에서 좋은 __hash__ 함수를 구현하는 방법

itboxs 2020. 9. 4. 07:05
반응형

파이썬에서 좋은 __hash__ 함수를 구현하는 방법


여러 속성이있는 클래스를 구현할 때 (아래의 장난감 예제와 같이) 해싱을 처리하는 가장 좋은 방법은 무엇입니까?

나는이 추측 __eq____hash__일치해야하지만, 어떻게 모든 속성을 처리 할 수있는 적절한 해시 함수를 구현하기 위해?

class AClass:
  def __init__(self):
      self.a = None
      self.b = None

  def __eq__(self, other):
      return other and self.a == other.a and self.b == other.b

  def __ne__(self, other):
    return not self.__eq__(other)

  def __hash__(self):
      return hash((self.a, self.b))

나는 튜플이 해시 가능하다는 이 질문대해 읽었 으므로 위의 예제와 같은 것이 합리적인지 궁금합니다. 맞나요?


__hash__동일한 객체에 대해 동일한 값을 반환해야합니다. 또한 객체의 수명 동안 변경되어서는 안됩니다. 일반적으로 불변 객체에 대해서만 구현합니다.

사소한 구현은 return 0. 이것은 항상 정확하지만 성능이 좋지 않습니다.

속성 튜플의 해시를 반환하는 솔루션이 좋습니다. 그러나 __eq__튜플에서 비교하는 모든 속성을 나열 할 필요는 없습니다 . 일부 속성이 일반적으로 같지 않은 객체에 대해 동일한 값을 갖는 경우에는 그대로 두십시오. 해시 계산을 필요한 것보다 더 비싸게 만들지 마십시오.

편집 : 일반적으로 해시를 혼합하기 위해 xor를 사용하지 않는 것이 좋습니다. 두 개의 다른 속성이 같은 값을 가질 때, 그들은 같은 해시를 가질 것이고, xor를 사용하면 서로를 취소 할 것입니다. 튜플은 해시를 혼합 더 복잡한 계산 사용을 참조하십시오 tuplehash에서 tupleobject.c.


쓰는 것은 위험하다

def __eq__(self, other):
  return other and self.a == other.a and self.b == other.b

rhs (즉, other) 객체가 부울 False로 평가되면 어떤 것과도 비교되지 않기 때문입니다!

또한 other의 클래스 또는 하위 클래스에 속 하는지 다시 확인할 수 있습니다 AClass. 그렇지 않은 경우 예외 AttributeError또는 거짓 긍정 (다른 클래스에 일치하는 값이있는 동일한 이름의 속성이있는 경우)이 발생합니다. 따라서 __eq__다음과 같이 다시 작성 하는 것이 좋습니다 .

def __eq__(self, other):
  return isinstance(other, self.__class__) and self.a == other.a and self.b == other.b

만일 속성이 이름으로 일치하는 한 관련없는 클래스를 비교하는 비정상적으로 유연한 비교를 원한다면, 적어도 추가 속성이없는 것을 피하고 AttributeError확인하는 other것이 좋습니다. 수행 방법은 상황에 따라 다릅니다 (객체의 모든 속성을 찾는 표준 방법이 없기 때문에).


문서화 object.__hash__(self)

유일한 필수 속성은 동일하게 비교되는 객체가 동일한 해시 값을 갖는 것입니다. 객체 비교에서 역할을하는 객체의 구성 요소에 대한 해시 값을 어떻게 든 함께 혼합 (예 : 배타적 또는 사용)하는 것이 좋습니다.

def __hash__(self):
    return hash(self.a) ^ hash(self.b)

참고 URL : https://stackoverflow.com/questions/4005318/how-to-implement-a-good-hash-function-in-python

반응형