2009-08-04 6 views
1

I은 ​​int S, float의 키로서 string S와 dict의 인스턴스를 가지고 있지만, 문제가 발생하는 경우이다 afloat을 같은 int 등과 b , 그리고 float(a) == b, 그리고 그들의 해시 값은 동일하며, 대응하는 값을 얻기 위해이 경우 고유 한 해시 값이 필요하기 때문에 얻지 않기를 원하는 것입니다.문제점 : 해시 (1) == 해시 (1.0)

예 :

d = {1:'1', 1.0:'1.0', '1':1, '1.0':1.0} 
d[1] == '1.0' 
d[1.0] == '1.0' 
d['1'] == 1 
d['1.0'] == 1.0 

내가해야 할 것은 :

d = {1:'1', 1.0:'1.0', '1':1, '1.0':1.0} 
d[1] == '1' 
d[1.0] == '1.0' 
d['1'] == 1 
d['1.0'] == 1.0 
+2

당신은이 작업을 수행 할 수 없습니다. 1.0 == 1 –

답변

7

1 == 1.0부터 hash(1) != hash(1.0) 인 경우 해시의 의미를 무시할 수 있습니다 (따라서 dicts 및 set). 더 일반적으로는 x == yhash(x) == hash(y)을 의미하며 항상 xy을 의미해야합니다 (물론 역 지형도를 유지해야하는 조건은 없습니다).

dict d에는 dict 표시로 작성한 두 번째 항목이 첫 번째 항목을 덮어 쓰기 때문에 3 개의 항목 만 있습니다. 당신은 또한 (다른 다른 메소드를 오버라이드 (override) 할 수 있습니다 당신의 정확한 필요에 따라

class W(object): 

    def __init__(self, x): 
    self.x = x 
    self.t = type(x) 

    def __eq__(self, other): 
    t = type(other) 
    if t != type(self): 
     return False 
    return self.x == other.x and self.t == other.t 

    def __hash__(self): 
    return hash(self.x)^hash(self.t) 

    def __getattr__(self, name): 
    return getattr(self.x, name) 

: 당신이 (더 일반적으로 숫자 반대)에만 동일한 종류의 사이에 개최 평등을 강제해야 할 경우, 같은 래퍼가 필요합니다 __cmp__ 또는 __le__과 같은 비교 방법, 산술 값, __repr__ 등). 어쨌든, 이것은 당신이 필요로하는 것과 비슷한 사전을 만들 수있게합니다. 1.0 대신에 1W(1.0) 대신에 W(1) 키를 사용하십시오. 숫자가 아닌 숫자는 줄이지 ​​않아도됩니다. 그렇게하기로 선택하면 모든 키가 똑같이 감싸는 경우 사용자의 dict에서 쉽게 검색 할 수 있습니다).

+0

포장 개체는 솔루션으로 간주 될 수 있으며 실제로 필요한 개체에 가깝습니다. 어쨌든, 다음과 같은 것에 대해 궁금합니다. h = hash ('a'); d = { 'a': 1, h : 2}; 결과는 d [ 'a']! = d [h]입니다. 왜냐하면 키의 해쉬 값은 같지만 타입이 동일하지 않기 때문에 dict 메쏘드 getitem은 키의 해쉬 값과 키의 타입을 모두 검사합니다. 그렇다면 int와 float에 대해 동일하게 수행되지 않는 이유는 무엇입니까? – mtasic85

+0

@mtasic, 왜 모든 문맥에서'1 == 1.0'인가, 아니면'dict'이 평등을 검사하는 다른 방법이 아닌'=='를 사용하는지 묻는가? '5.0 * x == 5.0 * y'의 경우 산술과 대수학의 가장 근본적인 기대를 깨지 않으면 서 어떻게 'x! = y'가 될 수 있을까요? 이것이 후자라면,'x == y'이지만'd [x]! = d [y]'이면'dict'는 어떻게 매핑 될 수 있습니까? 이것들은 강하고 소중하며 평등, 산술 및 색인에 대한 불변 속성이 강하게 기대되며 유형 훼 셜이 그들을 파멸시킬만한 이유가 없습니다. 평등은 항상 철학적 인 문제이지만 ... –

1

이 문제가 해결되지 않지만, Python 2.6's number documentation에서 :

구현자는 동일하게주의해야한다 숫자가 같고 동일한 값으로 해시됩니다.

플로트 1.00001 또는 그와 비슷한 것을 만들 수 있습니까?

6

사전 키로 float를 사용하면 '현명하지 않습니다'라는 것은 두 개의 부동 소수점이 동일한 값으로 평가된다는 것을 보장 할 수 없습니다.

키를 미리 결정된 소수 자릿수에 곱하고 그 정수를 키로 사용하는 것이 가장 좋습니다.

편집 : 미안 실제 숫자 키로 딕트를 원하지 않는 것 같아요. 단순히 입력 유형에 따라 출력을 포맷하고 싶습니까?

+0

좋은 지적이지만, 모든 중요한 유형에 대해 분리 된 dicts로 새로운 클래스를 생성 할 수 있다는 것을 알고 있습니다. 필요하면 __setitem__, __getitem__ 및 __delitem__ 메소드가 필요한 모든 유형에 대해 하나씩 추가 할 수 있습니다. 키와 값을 저장하기 위해 사용할 사전을 결정하십시오. – mtasic85

2

당신이 정말 같은 hackish 뭔가를 아마의 차이를 알아야 할 필요가있는 경우 :

x = '1' 
y = 1 

hash(type(x) + x) != hash(type(y) + y)