2016-07-18 5 views
6

python 클래스의 set()__hash__ 메서드를 사용하여 동일한 해시 개체를 추가하지 못하도록합니다. python data-model document에 따르면 set()은 동일한 개체로 동일한 해시 개체를 고려하고 한 번만 추가합니다.파이썬 클래스 __hash__ 메서드 및 집합

그러나 다른 아래와 같은 동작은 :

class MyClass(object): 

    def __hash__(self): 
     return 0 

result = set() 
result.add(MyClass()) 
result.add(MyClass()) 

print(len(result)) # len = 2 

동안 문자열 값의 경우, 올바르게 작동합니다.

result.add('aida') 
result.add('aida') 

print(len(result)) # len = 1 

제 질문은 : 왜 동일한 해시 객체가 세트에서 동일하지 않습니까?

답변

10

당신의 독서가 올바르지 않습니다

은 사용자 정의 두 개의 인스턴스가 동일한 것으로 가정된다 True 반환 __eq__ 방법을 추가합니다. 동등 검사에는 __eq__ 메서드가 사용됩니다. 이 문서에는 값이 및 ba == b (즉, a.__eq__(b))의 두 객체에 대해 동일해야한다는 내용 만 나와 있습니다.

이것은 일반적인 논리 실수입니다. a == b이 참일 경우 을 의미합니다. hash(a) == hash(b)도 참입니다. 그러나 의미가 반드시 등가을 의미하는 것은 아니며, hash(a) == hash(b)a == b을 의미합니다.

MyClass의 모든 인스턴스를 서로 동일하게 비교하려면 __eq__ 메서드를 제공해야합니다. 그렇지 않으면 파이썬은 신분을과 비교할 것입니다.이것은 할 수 있습니다 지금

class MyClass(object): 
    def __hash__(self): 
     return 0 
    def __eq__(self, other): 
     # another object is equal to self, iff 
     # it is an instance of MyClass 
     return isinstance(other, MyClass) 

:

: 현실에서

>>> result = set() 
>>> result.add(MyClass()) 
>>> result.add(MyClass()) 
1 

당신은 예를 들어, __eq__ 비교를 위해 사용되는 개체의 해당 속성에 __hash__ 기초 것

class Person 
    def __init__(self, name, ssn): 
     self.name = name 
     self.ssn = ssn 

    def __eq__(self, other): 
     return isinstance(other, Person) and self.ssn == other.ssn 

    def __hash__(self): 
     # use the hashcode of self.ssn since that is used 
     # for equality checks as well 
     return hash(self.ssn) 

p = Person('Foo Bar', 123456789) 
q = Person('Fake Name', 123456789) 
print(len({p, q}) # 1 
5

두 개의 객체를 해시 가능하게 만드는 두 세트 (__hash____eq__)가 필요합니다. 두 인스턴스 은 같은 것으로 간주 될 때이 동일한 해시 값을 반환해야합니다. 해시 값이 모두 인 경우 인스턴스가 이미 세트에있는 것으로 간주됩니다. 인스턴스는 해당 해시가 세트에있는 인스턴스 중 하나와 같다고 간주됩니다.

클래스에는 __eq__이 구현되어 있지 않으므로 object.__eq__이 대신 사용되며 obj1 is obj2도 true 인 경우에만 true를 반환합니다. 다시 말해서 두 인스턴스는 정확한 인스턴스 인 인 경우에만 동등한 것으로 간주됩니다.

해시가 일치하기 때문에 세트에 관한 한 고유하지 않습니다. 다른 해시를 가진 객체조차도 테이블 크기에 대한 해시의 인 모듈이 사용되므로 동일한 해시 테이블 슬롯으로 끝날 수 있습니다.

def __eq__(self, other): 
    if not isinstance(other, type(self)): 
     return False 
    # all instances of this class are considered equal to one another 
    return True