O que devo fazer para usar meus objetos de um tipo personalizado como chaves em um dicionário Python (onde não quero que o "ID do objeto" atue como chave), por exemplo
class MyThing:
def __init__(self,name,location,length):
self.name = name
self.location = location
self.length = length
Eu gostaria de usar o MyThing como chaves que são consideradas iguais se o nome e o local forem iguais. No C # / Java, estou acostumado a substituir e fornecer um método equals e hashcode e prometer não alterar nada do qual o hashcode dependa.
O que devo fazer em Python para fazer isso? Eu deveria mesmo?
(Em um caso simples, como aqui, talvez seja melhor colocar uma tupla (nome, localização) como chave - mas considere que eu gostaria que a chave fosse um objeto)
python
dictionary
Anonimato
fonte
fonte
MyThing
, se eles têm o mesmoname
elocation
, para indexar o dicionário para retornar o mesmo valor, mesmo se eles foram criados separadamente como dois "objetos" diferentes.Respostas:
Você precisa adicionar 2 métodos , observação
__hash__
e__eq__
:A documentação do dict do Python define esses requisitos nos objetos principais, ou seja, eles devem ser laváveis .
fonte
hash(self.name)
parece melhor do queself.name.__hash__()
, e se você o fizer, poderáhash((x, y))
evitar o XORing.x.__hash__()
assim também é errado , porque ele pode produzir incorretas resultados: pastebin.com/C9fSH7eFand
para,__eq__
mas depois pensei "por que não usar tuplas?" porque geralmente faço isso de qualquer maneira (acho que é mais legível). Por alguma estranha razão, meus olhos não voltaram a questionar__hash__
.__ne__()
foi "corrigido" .Uma alternativa no Python 2.6 ou superior é usar
collections.namedtuple()
- você economiza escrevendo quaisquer métodos especiais:fonte
Você substitui
__hash__
se deseja semântica hash especial e /__cmp__
ou__eq__
para tornar sua classe utilizável como chave. Objetos que comparam igual precisam ter o mesmo valor de hash.Python espera
__hash__
retornar um número inteiro,Banana()
não é recomendado retornar :)As classes definidas
__hash__
pelo usuário têm como padrão as chamadasid(self)
, como você observou.Existem algumas dicas extras na documentação .
fonte
__eq__
ou__cmp__
.__cmp__
é dado a você pelo Python se for uma classe definida pelo usuário, mas você provavelmente deseja substituí-los de qualquer maneira para acomodar novas semânticas.cmp
e usar=
classes de usuários que não substituam esses métodos, um deles deve ser implementado para atender ao requisito do questionador de que instâncias com nome e local semelhantes tenham a mesma chave de dicionário.