itsource

파이썬 데이터 클래스를 해시 가능하게 만들려면 어떻게 해야 합니까?

mycopycode 2023. 5. 12. 22:16
반응형

파이썬 데이터 클래스를 해시 가능하게 만들려면 어떻게 해야 합니까?

예를 들어, 나는 python3에 데이터 클래스가 있습니다.나는 이 물건들을 해시하고 주문할 수 있기를 원합니다.

나는 그들이 id만 주문하기를 원합니다.

문서에서 제가 _해쉬_와 그 모든 것을 구현할 수 있다는 것을 알 수 있습니다. 하지만 데이터 분석을 통해 이 작업을 수행하도록 하고 싶습니다. 왜냐하면 데이터 분석은 이 작업을 처리하기 위한 것이기 때문입니다.

from dataclasses import dataclass, field

@dataclass(eq=True, order=True)
class Category:
    id: str = field(compare=True)
    name: str = field(default="set this in post_init", compare=False)

a = sorted(list(set([ Category(id='x'), Category(id='y')])))

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'Category'

문서에서:

다음은 암시적 생성을 지배하는 규칙입니다.__hash__()방법:

[...]

한다면eq그리고.frozen기본적으로 둘 다 참입니다.dataclass()를 생성합니다.__hash__()당신을 위한 방법.한다면eq사실이고frozen거짓입니다.__hash__()로 설정됩니다.None그것을 씻을 수 없음으로 표시하는 것(즉, 그것은 변화할 수 있기 때문입니다.한다면eq거짓입니다.__hash__()손도 대지 않은 채로 남을 것이라는 것은__hash__()superclass의 메서드가 사용됩니다(superclass가 객체인 경우, 이는 ID 기반 해싱으로 되돌아간다는 것을 의미합니다).

설정한 이후eq=True왼쪽으로frozen기본값(False), 데이터 클래스를 삭제할 수 없습니다.

세 가지 옵션이 있습니다.

  • 세트frozen=True(게다가eq=True), 이는 클래스를 불변하고 해시 가능하게 만듭니다.
  • 세트unsafe_hash=True그것은 그것을 만들 것입니다.__hash__클래스를 변경할 수 있는 상태로 두므로 딕터 세트에 저장된 동안 클래스 인스턴스가 수정될 경우 문제가 발생할 위험이 있습니다.

    cat = Category('foo', 'bar')
    categories = {cat}
    cat.id = 'baz'
    
    print(cat in categories)  # False
    
  • 수동으로 구현__hash__방법.

TL;DR

사용하다frozen=True와 함께eq=True(이는 인스턴스를 불변으로 만들 것입니다.)

긴 대답

문서에서:

__hash__()기본 제공 프로그램에서 사용됨hash()개체가 사전 및 세트와 같은 해시된 컬렉션에 추가되는 경우.가지고 있는 것.__hash__()클래스의 인스턴스가 불변함을 의미합니다.가변성은 프로그래머의 의도, 존재 및 행동에 따라 달라지는 복잡한 속성입니다.__eq__()그리고 eq와 냉동 플래그의 값.dataclass()장식가

기본적으로,dataclass()암시적으로 a를 추가하지 않습니다.__hash__()안전하지 않은 한 방법.명시적으로 정의된 기존 시스템을 추가하거나 변경하지 않습니다.__hash__()방법.클래스 속성 설정__hash__ = None에서 설명한 것처럼 Python에 대한 특정 의미가 있습니다.__hash__() 문서화

한다면__hash__()명시적으로 정의되지 않았거나 없음으로 설정된 경우dataclass()암시적으로 추가할 수 있습니다.__hash__()방법.권장되지는 않지만 강제로 실행할 수 있습니다.dataclass()를 생성하기 위해__hash__()와의 방법.unsafe_hash=True이는 클래스가 논리적으로 불변하지만 변형될 수 있는 경우에 해당할 수 있습니다.이는 전문적인 사용 사례이므로 신중하게 고려해야 합니다.

인 생성 규칙입니다.__hash__() 명시적으로 둘 수는 하시기 바랍니다.__hash__() in set 데터클및세의메서드트이를 설정합니다.unsafe_hash=True이것은 결과를 초래할 것입니다.TypeError.

참인 경우 으로 eq는 frozen이 됩니다.dataclass()합니다.__hash__()당신을 위한 방법.false이면 eq는 frozen이고,__hash__()없음으로 설정되어 해시할 수 없음으로 표시됩니다(변경 가능하므로).거짓이라면, eq 거짓이면가,면,__hash__()손도 대지 않은 채로 남을 것이라는 것은__hash__()superclass의 메서드가 사용됩니다(superclass가 객체인 경우, 이는 ID 기반 해싱으로 되돌아간다는 것을 의미합니다).

unsafe_hash 사용을 위한 특별한 메모를 추가하고 싶습니다.

compare=False 또는 hash=False를 설정하여 해시 비교에서 필드를 제외할 수 있습니다.(기본적으로 비교에서 상속됨).

이 기능은 노드를 그래프에 저장하지만 해싱을 중단하지 않고 방문한 노드를 표시하려는 경우에 유용할 수 있습니다(예: 방문하지 않은 노드 집합에 있는 경우)

from dataclasses import dataclass, field
@dataclass(unsafe_hash=True)
class node:
    x:int
    visit_count: int = field(default=10, compare=False)  # hash inherits compare setting. So valid.
    # visit_count: int = field(default=False, hash=False)   # also valid. Arguably easier to read, but can break some compare code.
    # visit_count: int = False   # if mutated, hashing breaks. (3* printed)

s = set()
n = node(1)
s.add(n)
if n in s: print("1* n in s")
n.visit_count = 11
if n in s:
    print("2* n still in s")
else:
    print("3* n is lost to the void because hashing broke.")

이걸 알아내는데 몇 시간이나 걸렸어요제가 찾은 유용한 추가 판독치는 데이터 클래스에 대한 파이썬 문서입니다.구체적으로 필드 설명서 및 데이터 클래스 인수 설명서를 참조하십시오.https://docs.python.org/3/library/dataclasses.html

언급URL : https://stackoverflow.com/questions/52390576/how-can-i-make-a-python-dataclass-hashable

반응형