¿Qué debo hacer para usar mis objetos de un tipo personalizado como claves en un diccionario de Python (donde no quiero que el "ID del objeto" actúe como la clave), por ejemplo?
class MyThing:
def __init__(self,name,location,length):
self.name = name
self.location = location
self.length = length
Me gustaría usar MyThing como claves que se consideran iguales si el nombre y la ubicación son los mismos. Desde C # / Java estoy acostumbrado a tener que anular y proporcionar un método igual y de código hash, y prometo no mutar nada de lo que depende el código hash.
¿Qué debo hacer en Python para lograr esto? ¿Debo incluso?
(En un caso simple, como aquí, tal vez sería mejor simplemente colocar una tupla (nombre, ubicación) como clave, pero tenga en cuenta que me gustaría que la clave sea un objeto)
python
dictionary
Seudónimo
fuente
fuente

MyThing, si tienen el mismonameylocation, para indexar el diccionario para que devuelva el mismo valor, incluso si se crearon por separado como dos "objetos" diferentes.Respuestas:
Necesita agregar 2 métodos , nota
__hash__y__eq__:La documentación de dict de Python define estos requisitos en los objetos clave, es decir, deben ser hashaable .
fuente
hash(self.name)se ve mejor queself.name.__hash__(), y si lo haces y puedes hacerlohash((x, y))para evitar XORing a ti mismo.x.__hash__()así también está mal , porque puede producir resultados incorrectos : pastebin.com/C9fSH7eFandpara__eq__pero luego pensé "¿por qué no usar tuplas?" porque a menudo hago eso de todos modos (creo que es más legible).__hash__Sin embargo, por alguna extraña razón, mis ojos no volvieron a preguntar .__ne__()ha sido "arreglado" .Se debe utilizar una alternativa en Python 2.6 o superior
collections.namedtuple(): le ahorra escribir cualquier método especial:fuente
Se anula
__hash__si desea una semántica hash especial,__cmp__o__eq__para que su clase sea utilizable como clave. Los objetos que comparan igual deben tener el mismo valor hash.Python espera
__hash__devolver un número entero,Banana()no se recomienda regresar :)Las clases definidas por el usuario tienen
__hash__por defecto que las llamadasid(self), como usted notó.Hay algunos consejos adicionales de la documentación :
fuente
__eq__o__cmp__.__cmp__Python te lo da si es una clase definida por el usuario, pero probablemente quieras anularlos de todos modos para acomodar la nueva semántica.cmpy usar=en clases de usuario que no anulan estos métodos, uno de ellos debe implementarse para cumplir con el requisito del interrogador de que las instancias con nombre y ubicación similares tengan la misma clave de diccionario.