2011-02-14 4 views
2

내 개체를 올바르게 해싱하는 데 문제가 있습니다. 나는 모든 추가 Foo 개체에 따라서 같은 내용, 같은 해시를 갖고 있기 때문에, 단일 요소를 포함하도록 설정 결과를 기대동일한 해시 값이지만 __hash__을 재정의 한 후 동일한 개체가 아닙니다.

class Foo: 
    def __init__(self, bar): 
     self.keys = list(bar.keys()) 
     self.values = list(bar.values())  
    def __str__(self): 
     return ', '.join('%s: %s' % z for z in zip(self.keys, self.values))  
    def __hash__(self): 
     return hash(str(self)) 

if __name__ == '__main__': 
    result = set() 
    d = { 1: 2, 3: 4, 5: 6, 7: 8 } 
    for i in range(10): 
     result.add(Foo(d)) 
    for r in result: 
     print r, hash(r) 

다음 코드를 살펴 보자. 문제는 여기에 무엇

[email protected]:~/Desktop/stackoverflow$ python hashproblem.py 
1: 2, 3: 4, 5: 6, 7: 8 2131119371379196338 
1: 2, 3: 4, 5: 6, 7: 8 2131119371379196338 
1: 2, 3: 4, 5: 6, 7: 8 2131119371379196338 
1: 2, 3: 4, 5: 6, 7: 8 2131119371379196338 
1: 2, 3: 4, 5: 6, 7: 8 2131119371379196338 
1: 2, 3: 4, 5: 6, 7: 8 2131119371379196338 
1: 2, 3: 4, 5: 6, 7: 8 2131119371379196338 
1: 2, 3: 4, 5: 6, 7: 8 2131119371379196338 
1: 2, 3: 4, 5: 6, 7: 8 2131119371379196338 
1: 2, 3: 4, 5: 6, 7: 8 2131119371379196338 

:

그러나,이 결과인가? 해시는과 동일하므로 내장 된 set 개체로 복제본으로 처리해서는 안됩니까? 세트에 중복 된 내용이 포함되어있는 이유는 무엇입니까?

요소를 집합에 추가 할 때 Foo(d) 대신 str(Foo(d))을 사용하면 예상대로 작동하는 것으로 나타났습니다. 왜 중요합니까?

파이썬 버전은 다음과 같습니다 __hash__ 방법은 내부 해시 테이블에 사용되기 때문에

[email protected]:~/Desktop/stackoverflow$ python --version 
Python 2.6.6 

답변

4

, 당신은뿐만 아니라 __eq__를 재정의해야합니다.

__eq__ 만 재정의하는 것이 잘못되었습니다. 두 객체가 같으면 (a.__eq__(b) == True) hash(a)hash(b)이 같아야합니다.

기본 __hash__ 방법은 다음과 같습니다

def __hash__(self): 
    return id(self) 
+0

감사합니다. 그것은 작동하는 것 같습니다. '__hash__'를 오버라이드 할 필요가 있습니까, 아니면'__eq__'로 충분합니까? – misha

+0

@misha, 객체의 디폴트'__hash__'는'return id (self)'입니다. 엄격하게 오버라이드 할 필요는 없습니다. – vz0

+0

나는'__eq__'을 구현하지만'__hash__'을 구현하지 않는 것이이 예제를 깰 것이라고 생각합니다. 'Foo (d)'는 10 개의 새로운'Foo' 인스턴스를 생성합니다. 아마도'dict' 구현은 같은 해시 버킷에서 등가 키만 찾습니다. – Mikel

관련 문제