class A(object):
x = 4
i = A()
d = {}
d[i] = 2
print d
i.x = 10
print d
나는 불변의 객체 만 사전 키가 될 수 있다고 생각했지만 위의 객체는 변경 가능하다고 생각했습니다.나는 python에서 사전 키로 변경 가능한 객체를 사용할 수 있습니다. 이것은 허용되지 않습니까?
class A(object):
x = 4
i = A()
d = {}
d[i] = 2
print d
i.x = 10
print d
나는 불변의 객체 만 사전 키가 될 수 있다고 생각했지만 위의 객체는 변경 가능하다고 생각했습니다.나는 python에서 사전 키로 변경 가능한 객체를 사용할 수 있습니다. 이것은 허용되지 않습니까?
__hash__ 메서드가있는 모든 객체는 사전 키가 될 수 있습니다. 당신이 쓰는 클래스의 경우, 값을 반환하려면이 메서드는 기본적으로 ID (자기)를 기반으로, 평등은 해당 클래스에 대한 정체성에 의해 결정되어 있지 않은 경우, 당신은 키로를 사용하여 놀랄 수
>>> class A(object):
... def __eq__(self, other):
... return True
...
>>> one, two = A(), A()
>>> d = {one: "one"}
>>> one == two
True
>>> d[one]
'one'
>>> d[two]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: <__main__.A object at 0xb718836c>
>>> hash(set()) # sets cannot be dict keys
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'set'
버전 2.6에서 변경되었습니다 : __hash__을 None으로 설정하여 클래스 인스턴스를 해쉬 할 수없는 것으로 명시 적으로 표시 할 수 있습니다. [__hash__]
class Unhashable(object):
__hash__ = None
요건은 객체의 해시가 시간에 따라 변화하지 않는 것으로하고, 그 원래의 값과 동일 (==) 비교 유지있다. 클래스 A는이 두 요구 사항을 모두 충족하므로 유효한 사전 키를 만듭니다. x 속성은 키잉에서 전혀 고려되지 않고, 객체 ID 만이 고려됩니다.
개체가 hashable 인 경우 사전의 키가 될 수 있습니다. 여기
는 문서로부터 해쉬의 정의이다그것의 수명 동안 변경되지 않을 해시 값을 가지면 목적은 해쉬이다는 (그것이
__hash__()
방법이 필요), 및 다른 비교 될 수있다 개체 (__eq__()
또는__cmp__()
메서드 필요). equal을 비교하는 해시 가능 객체는 동일한 해시 값을 가져야합니다.해시 가능성 (Hashability)은 해시 값을 내부적으로 사용하기 때문에 해시 성은 개체를 사전 키 및 집합 멤버로 사용할 수있게합니다.
변경 가능한 모든 컨테이너 (예 : 목록 또는 사전)는 존재하지 않지만 모든 Python의 변경 불가능한 내장 객체는 해시 가능합니다. 사용자 정의 클래스의 인스턴스 인 객체는 기본적으로 해시 가능합니다. 그들은 모두 같지 않은 것을 비교하고 해시 값은 id()입니다.
object
이후
이이 명시 적으로 해쉬 수 없습니다 정의하지 않는 한 object
에서 파생 아무것도 해쉬 것을 의미 __hash__
, __eq__
및 __cmp__
의 기본 구현을 제공합니다. 해시 가능 인 변경 가능 유형을 작성하는 것이 허용되지 않지만 원하는대로 작동하지 않을 수 있습니다. 프레드 - nurk의 예 @
위 다행히 때문에 더 이상 this change의 파이썬 3에서 작동하지 않습니다 :
그 하나님 께 감사를드립니다 ... 적절한
__eq__()
을 무시하고__hash__()
암시None
로 설정해야합니다__hash__()
를 정의하지 않는 클래스입니다. 클래스의__hash__()
방법은None
경우 프로그램이 자신의 해시 값을 검색하려고 할 때, 클래스의 인스턴스는
TypeError
을 올릴 것이다.그러나 직접
__hash__()
을 정의하면 여전히 악의적 인 일을 할 수 있습니다.
class BadHasher:
def __init__(self):
self.first = True
# Implement __hash__ in an evil way. The first time an instance is hashed,
# return 1. Every time after that, return 0.
def __hash__(self):
if self.first:
self.first = False
return 1
return 0
myobject = BadHasher()
# We can put this object in a set...
myset = {myobject}
# ...but as soon as we look for it, it's gone!
if myobject not in myset:
print("what the hell we JUST put it in there")