사전 키로 사용자 지정 유형의 개체
커스텀 타입의 오브젝트를 Python 사전의 키로 사용하려면 어떻게 해야 합니까(예를 들어 "object id"가 키로 동작하지 않도록 합니다).
class MyThing:
def __init__(self,name,location,length):
self.name = name
self.location = location
self.length = length
이름과 위치가 같다면 MyThing을 같은 키로 사용하고 싶습니다.C#/Java부터 등가 및 해시 코드 방식을 덮어쓰고 제공하는 데 익숙해져 있으며 해시 코드가 의존하는 어떤 것도 변환하지 않겠다고 약속합니다.
이를 위해 Python에서 무엇을 해야 합니까?나도 할까?
(여기처럼 간단한 경우에는 (이름, 장소) 태플을 키로 하는 것이 좋을지도 모릅니다만, 키를 오브젝트로 하고 싶다고 생각하고 있습니다).
두 가지 방법을 추가해야 합니다.__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__
당신의 수업을 열쇠로 사용할 수 있도록 하기 위해서입니다.같은 값을 비교하는 개체는 동일한 해시 값을 가져야 합니다.
Python이 기대하는 것은__hash__
정수를 반환하다Banana()
는 권장되지 않습니다. : )
사용자 정의 클래스에는__hash__
디폴트로는가 호출합니다.id(self)
말씀하신 대로입니다.
이 매뉴얼에는 몇 가지 추가 힌트가 있습니다.
를 상속하는 클래스
__hash__()
부모 클래스에서 메서드를 사용하지만 의미를 변경하다__cmp__()
또는__eq__()
반환된 해시 값이 더 이상 적절하지 않은 경우(예를 들어 기본 ID 기반 등식이 아닌 값 기반 등식의 개념으로 전환됨)로 설정함으로써 명시적으로 캐시 불능으로 플래그를 지정할 수 있다.__hash__ = None
클래스 정의에서 사용합니다.이렇게 하면 프로그램이 해시 값을 가져오려고 할 때 클래스의 인스턴스가 적절한 TypeError를 발생시킬 뿐만 아니라 체크 시 캐시 불능으로 올바르게 식별됩니다.isinstance(obj, collections.Hashable)
(자신을 정의하는 계층과는 달리)__hash__()
TypeError를 명시적으로 올립니다).
python 3.8.8(아마도 이전부터)에서는 더 이상 명시적으로 선언할 필요가 없다는 것을 알게 되었습니다.__eq__()
그리고.__hash__()
자신의 수업을 딕트의 키로 사용할 수 있는 기회를 가질 수 있습니다.
class Apple:
def __init__(self, weight):
self.weight = weight
def __repr__(self):
return f'Apple({self.weight})'
apple_a = Apple(1)
apple_b = Apple(1)
apple_c = Apple(2)
apple_dictionary = {apple_a : 3, apple_b : 4, apple_c : 5}
print(apple_dictionary[apple_a]) # 3
print(apple_dictionary) # {Apple(1): 3, Apple(1): 4, Apple(2): 5}
Python이 스스로 관리하고 있다고 생각합니다만, 제가 틀릴 수도 있습니다.
오늘의 답은 다른 사람들이 나처럼 여기 오게 될 수도 있다는 것을 알고 있기 때문에 python > 3.7의 데이터클래스를 사용하는 것입니다.해시 함수와 eq 함수를 모두 갖추고 있습니다.
언급URL : https://stackoverflow.com/questions/4901815/object-of-custom-type-as-dictionary-key
'programing' 카테고리의 다른 글
AWS RDS MariaDB가 이유 없이 단순 대체 테이블에서 300GB를 소비함 (0) | 2022.09.24 |
---|---|
다른 프로그래밍 언어로 번역하기 쉽게 하기 위해 코드에 어떤 패턴을 적용할 수 있습니까? (0) | 2022.09.24 |
PHP array()와 []의 차이점 (0) | 2022.09.24 |
표준 각도JS 워크플로우 및 프로젝트 구조(Python Flask 포함) (0) | 2022.09.24 |
JPQL 쿼리를 사용하여 여러 스키마에서 데이터 선택 (0) | 2022.09.23 |