[python] 사전 키로서의 커스텀 타입의 객체

파이썬 딕셔너리에서 커스텀 타입의 객체를 키로 사용하려면 어떻게해야합니까 ( “object id”를 키로 사용하지 않기를 원합니다)

class MyThing:
    def __init__(self,name,location,length):
            self.name = name
            self.location = location
            self.length = length

이름과 위치가 같은 경우 MyThing을 동일한 키로 사용하고 싶습니다. C # / Java에서 equals 및 hashcode 메서드를 재정의하고 제공해야하며 해시 코드가 의존하는 것을 변경하지 않도록 약속했습니다.

이것을 달성하기 위해 파이썬에서 무엇을해야합니까? 나도해야합니까?

(단순한 경우, 여기에서와 같이 (이름, 위치) 튜플을 키로 배치하는 것이 좋습니다. 그러나 키를 객체로 만들고 싶습니다.)



답변

당신은 추가해야 할 2 가지 방법 ,주의 __hash____eq__:

class MyThing:
    def __init__(self,name,location,length):
        self.name = name
        self.location = location
        self.length = length

    def __hash__(self):
        return hash((self.name, self.location))

    def __eq__(self, other):
        return (self.name, self.location) == (other.name, other.location)

    def __ne__(self, other):
        # Not strictly necessary, but to avoid having both x==y and x!=y
        # True at the same time
        return not(self == other)

Python dict 문서 는 주요 객체에 대한 이러한 요구 사항을 정의합니다. 즉, 해시 가능 해야합니다 .


답변

Python 2.6 이상의 대안은 사용 collections.namedtuple()하는 것입니다. 특별한 방법을 쓰지 않아도됩니다.

from collections import namedtuple
MyThingBase = namedtuple("MyThingBase", ["name", "location"])
class MyThing(MyThingBase):
    def __new__(cls, name, location, length):
        obj = MyThingBase.__new__(cls, name, location)
        obj.length = length
        return obj

a = MyThing("a", "here", 10)
b = MyThing("a", "here", 20)
c = MyThing("c", "there", 10)
a == b
# True
hash(a) == hash(b)
# True
a == c
# False


답변

__hash__특수 해시 시맨틱을 원하면 재정의 __cmp__하거나__eq__ 클래스를 키로 사용할 수 있도록하려면 하십시오. 동등하게 비교하는 객체는 동일한 해시 값을 가져야합니다.

파이썬 __hash__은 정수를 반환 할 것으로 예상 하지만 반환은 Banana()권장하지 않습니다 🙂

사용자 정의 클래스는 __hash__기본적으로 id(self)언급 한 것처럼 을 호출합니다 .

설명서의 추가 팁이 있습니다 .

상속 클래스 __hash__()
의 부모 클래스의 메소드를하지만의 의미를 변경 __cmp__()또는 __eq__()
반환 된 해시 값이 더 이상 적합하지 않도록 (예를 들어, 대신 기본 ID를 기반으로 평등 평등의 가치를 기반으로 개념을 전환하여)로 플래그를 명시 적으로 자신을 수 __hash__ = None
클래스 정의에서 설정 하여 해싱 할 수 없습니다 . 그렇게하면 프로그램이 해시 값을 검색하려고 할 때 클래스의 인스턴스가 적절한 TypeError를 발생시킬뿐만 아니라 검사 할 때 해시 할 수없는 것으로 올바르게 식별됩니다
isinstance(obj, collections.Hashable)
( __hash__()TypeError를 명시 적으로 발생 시키는 클래스와 달리
).


답변