파이썬에서 "해시 가능"은 무엇을 의미합니까?


194

인터넷 검색을 시도했지만 해시 가능의 의미를 찾을 수 없습니다.

그들이 물건이라고 말 hashable하거나 hashable objects무엇을 의미합니까?


1
해시 가능__hash__()메소드 에 대한 문서를 참조하십시오 .
ʇsәɹoɈ

5
hasable 객체 또는 무언가를 검색하지만, 어떤 링크도 해시 가능이 실제로 무엇을 의미하는지 설명하지 않습니다
user1755071

답변:


181

로부터 파이썬 용어 :

객체는 수명 동안 변경되지 않는 ( __hash__()메소드 필요 ) 해시 값이 있고 다른 객체 ( __eq__()또는 __cmp__()메소드 필요)와 비교할 수있는 경우 해시 가능합니다 . 동일하게 비교하는 해시 가능 객체는 동일한 해시 값을 가져야합니다.

해시 기능을 사용하면 객체가 사전 키 및 집합 멤버로 사용할 수 있습니다. 이러한 데이터 구조는 해시 값을 내부적으로 사용하기 때문입니다.

파이썬의 변경 불가능한 내장 객체는 모두 해시 가능하지만 변경 가능한 컨테이너 (예 : 목록 또는 사전)는 없습니다. 사용자 정의 클래스의 인스턴스 인 객체는 기본적으로 해시 가능합니다. 그들은 모두 불평등을 비교하며 해시 값은 그들의 것 id()입니다.


2
이 경우 hash value현재 해시 값 것입니다. 당신은 몇 가지 예를 들어 줄 수 있습니다
user1755071

2
@ user55711 : 여기서 해시 값은을 호출 한 결과입니다 __hash__(). 보다 일반적으로 en.wikipedia.org/wiki/Hash_function
NPE를

16
@TorstenBronger : 동일하지 않은 두 객체가 같은 값으로 해시 될 수 있기 때문입니다. 즉, 해싱이 손실됩니다.
NPE

1
python-2.7.12에서 결과 id(object)는의 16 배입니다 object.__hash__(). 따라서이 버전의 용어집 발췌는 올바르지 않습니다. 해시 값은 아니지만 id()python 2.7.12의 업데이트 된 문서에서 언급했듯이 파생 값에서 파생됩니다.
davidA

2
나는 이것이 오래된 게시물이라는 것을 알고 있지만 여기에 복사 된 용어집 항목이 완전히 정확하지 않다는 것을 언급 할 가치가 있습니다. 튜플 안에 변경 가능한 객체 (예 : 목록)를 넣을 수 있습니다. 튜플은 여전히 ​​불변이지만 그 안에있는 목록을 변경할 수 있으므로 해시 가능하지 않습니다. 시도 hash((1, [2, 3]))액션에서 볼 수 있습니다. 해시 가능에 대한 용어집 항목을 수정하라는 요청을 게시했습니다.
John Riehl

102

여기에있는 모든 대답에는 파이썬에서 해시 가능한 객체에 대한 효과적인 설명이 있지만 해싱이라는 용어를 먼저 이해해야한다고 생각합니다.

해싱 은 많은 양의 데이터를 빠르게 저장하고 액세스하는 고성능 의사 랜덤 액세스 데이터 구조를 만드는 데 사용되는 컴퓨터 과학의 개념입니다.

예를 들어 전화 번호가 10,000 개이고 배열 (연속적인 메모리 위치에 데이터를 저장하고 임의 액세스를 제공하는 순차적 데이터 구조)에 저장하려는 경우 필요한 양의 연속성이 없을 수 있습니다. 메모리 위치.

따라서 대신 크기가 100 인 배열을 사용하고 해시 함수를 사용하여 값 집합을 동일한 인덱스에 매핑하면 이러한 값을 연결된 목록에 저장할 수 있습니다. 이것은 어레이와 비슷한 성능을 제공합니다.

이제 해시 함수는 숫자를 배열의 크기로 나누고 나머지를 인덱스로 사용하는 것처럼 간단 할 수 있습니다.

자세한 내용은 https://en.wikipedia.org/wiki/Hash_function참조하십시오.

또 다른 좋은 참고 자료는 다음과 같습니다. http://interactivepython.org/runestone/static/pythonds/SortSearch/Hashing.html


1
해싱에 대한 흥미로운 관점입니다. 나는 그런 식으로 생각하지 않았습니다.
yuvgin 2012 년

@yuvgin 해시 테이블은 종종 희소 배열을 구현하는 데 사용됩니다 (예 : 여기에 주어진 예).
Eli Korvigo

@EliKorvigo 저는 일반 배열을 단순히 최적화 된 해시 테이블 버전으로 생각합니다.
Mark Ransom

1
전화 번호 배열 시나리오에 관한 간단한 코드를 생성하여 해싱 개념을 명확히 할 수 있습니까?
Istiaque Ahmed

18

변경할 수없는 (변경 가능한 수단, 변경 가능성이있는) 항목은 해시 할 수 있습니다. 예를 들어 클래스에 클래스가 있으면 해시 함수를 찾아야합니다. 방법을 dir(tuple)찾고 __hash__여기에 몇 가지 예가 있습니다.

#x = hash(set([1,2])) #set unhashable
x = hash(frozenset([1,2])) #hashable
#x = hash(([1,2], [2,3])) #tuple of mutable objects, unhashable
x = hash((1,2,3)) #tuple of immutable objects, hashable
#x = hash()
#x = hash({1,2}) #list of mutable objects, unhashable
#x = hash([1,2,3]) #list of immutable objects, unhashable

불변 타입의리스트 :

int, float, decimal, complex, bool, string, tuple, range, frozenset, bytes

변경 가능한 유형 목록 :

list, dict, set, bytearray, user-defined classes

최근 Ellipsis에이 또한 불변 유형이며의 키로 사용될 수 있음을 알았습니다 dict.
Gábor Fekete

사용자 정의 클래스조차도 사용할 수 있지만 인스턴스 이름은 사용할 수 없습니다. 예 :hash(MyClass)
Gábor Fekete

1
GáborFekete @ 사용자 정의 클래스의 인스턴스는 클래스가 구현하는 경우 해쉬 있습니다 __hash____eq__. 또한 모든 사용자 정의 클래스는 이러한 메소드를 구현하므로 object(범용 기본 클래스) 에서 메소드를 상속하므로 해시 가능 합니다.
Eli Korvigo

7

파이썬 용어에 따르면 필자는 해시 가능한 객체의 인스턴스를 만들 때 인스턴스의 멤버 또는 값에 따라 변경 불가능한 값도 계산됩니다. 예를 들어,이 값을 아래와 같이 dict의 키로 사용할 수 있습니다.

>>> tuple_a = (1,2,3)
>>> tuple_a.__hash__()
2528502973977326415
>>> tuple_b = (2,3,4)
>>> tuple_b.__hash__()
3789705017596477050
>>> tuple_c = (1,2,3)
>>> tuple_c.__hash__()
2528502973977326415
>>> id(a) == id(c)  # a and c same object?
False
>>> a.__hash__() == c.__hash__()  # a and c same value?
True
>>> dict_a = {}
>>> dict_a[tuple_a] = 'hiahia'
>>> dict_a[tuple_c]
'hiahia'

tuple_a와 tuple_c의 해시 값은 동일한 멤버를 갖기 때문에 동일하다는 것을 알 수 있습니다. dict_a의 키로 tuple_a를 사용하면 dict_a [tuple_c]의 값이 동일하다는 것을 알 수 있습니다. 즉, dict의 키로 사용될 때 해시 값이 같기 때문에 동일한 값을 반환합니다. 똑같다. 해시 가능 하지 않은 객체의 경우 해시 메소드 는 없음으로 정의됩니다.

>>> type(dict.__hash__) 
<class 'NoneType'>

이 해시 값은 동적으로가 아닌 인스턴스 초기화시 계산되므로 불변의 객체 만 해시 가능합니다. 도움이 되었기를 바랍니다.


4

파이썬에서 해시 가능한 객체를 이해하는 실제 예를 들어 보겠습니다. 이 예제에서는 2 개의 튜플을 사용하고 있습니다. 튜플의 각 값에는 고유 한 해시 값이 있으며 수명 기간 동안 절대 변하지 않습니다. 따라서이 값을 기반으로 두 튜플 간의 비교가 수행됩니다. Id ()를 사용하여 튜플 요소의 해시 값을 얻을 수 있습니다.

2 개의 튜플 비교두 튜플의 동등성


26
이것은 이미지보다는 텍스트로 더 유용 할 것입니다.
baxx

7
정답입니다. id ()는 메모리에서 참조 된 주소를 보여줍니다. 해시 값이 아닙니다. 해시를 얻으려면 __hash __ () 함수를 사용하십시오. 예 : t1 .__ hash __ ()
Vlad

@ascentman 틀렸다고 생각되는 답변을 편집하는 것을 망설이지 마십시오. 귀하의 편집 내용은 동료 검토를 거쳐 수락 될 경우 작은 점수의 보상을받습니다.
XavierStuvw

4

파이썬에서는 객체가 인덱스를 반환하기 위해 세트의 멤버가 될 수 있음을 의미합니다. 즉, 고유 한 ID / ID가 있습니다.

예를 들어, 파이썬 3.3에서 :

데이터 구조리스트는 해시 가능하지 않지만 데이터 구조 터플은 해시 가능합니다.


해시는 id(대략) 메모리에있는 객체의 주소 인와 동일하지 않습니다 .
poolie

3

해시 가능 = 해시 가능

좋아, 해싱이란 무엇인가? 해싱 함수는 "Python"과 같은 문자열과 같은 개체를 가져 와서 고정 크기 코드를 반환하는 함수입니다. 간단히하기 위해 반환 값이 정수라고 가정합니다.

Python 3에서 hash ( 'Python')을 실행하면 결과로 5952713340227947791이 표시됩니다. 다른 버전의 Python은 기본 해시 함수를 자유롭게 변경할 수 있으므로 다른 값을 얻을 수 있습니다. 중요한 것은 지금 여러 번 해시 ( 'Python')를 실행하더라도 항상 동일한 버전의 Python으로 동일한 결과를 얻을 수 있다는 것입니다.

그러나 hash ( 'Java')는 1753925553814008565를 반환합니다. 따라서 해싱하는 객체가 변경되면 결과도 변경됩니다. 반면 해싱중인 객체가 변경되지 않으면 결과는 동일하게 유지됩니다.

이것이 왜 중요한가?

예를 들어, 파이썬 사전은 키를 변경할 수 없어야합니다. 즉, 키는 변경되지 않는 객체 여야합니다. 문자열은 다른 기본 유형 (int, float, bool)과 마찬가지로 Python에서 변경할 수 없습니다. 튜플 및 고정 세트도 변경할 수 없습니다. 반면, 목록은 변경할 수 없기 때문에 변경할 수 없습니다 (즉, 변경할 수 있음). 마찬가지로 dicts도 변경할 수 있습니다.

따라서 무언가 해쉬 가능하다고 말할 때, 그것은 불변이라는 것을 의미합니다. 변경 가능한 유형을 hash () 함수에 전달하려고하면 실패합니다.

>>> hash('Python')
1687380313081734297
>>> hash('Java')
1753925553814008565
>>>
>>> hash([1, 2])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'
>>> hash({1, 2})
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'set'
>>> hash({1 : 2})
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'dict'
>>>
>>> hash(frozenset({1, 2}))
-1834016341293975159
>>> hash((1, 2))
3713081631934410656

1
파이썬은 각 프로세스가 시작될 때 무작위로 해싱 알고리즘을 시드합니다. 따라서 다른 프로세스에서 hash ( 'Python')을 두 번 실행하면 실제로 다른 해시 값을 얻게됩니다.
D 허드슨

2

파이썬에서, 불변 객체 (정수, 부울, 문자열, 튜플 등)는 해시 가능합니다. 즉, 수명 동안 값이 변경되지 않습니다. 이를 통해 파이썬은 고유 한 해시 값을 만들어이를 식별 할 수 있습니다. 사전에서 고유 키를 추적하고 고유 값을 추적하는 데 사용할 수 있습니다.

그렇기 때문에 파이썬에서는 사전의 키에 대해 불변의 데이터 유형을 사용해야합니다.


-1

처음부터 해싱 테이블을 만들려면 모든 값을 "없음"으로 설정하고 요구 사항이 발생하면 수정해야합니다. 해시 가능한 객체는 수정 가능한 데이터 유형 (사전, 목록 등)을 나타냅니다. 반면 세트는 일단 할당되면 다시 초기화 할 수 없으므로 세트를 해시 할 수 없습니다. 반면 set ()의 변형-frozenset ()은 해시 가능합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.