2009-08-09 30 views
45

Esto sería similar al método java.lang.Object.hashcode()¿Hay un identificador único de objeto en Python?

Necesito almacenar objetos que no tengo control en un conjunto, y me aseguro de que solo si dos objetos son en realidad el mismo objeto (no contienen los mismos valores) se sobreescribirán los valores.

+5

Tenga en cuenta que 'hashCode()' en Java no es necesariamente única, que sólo tiene un poco de cuidado elegido semántica en conjunción con 'igual()'. – Joey

+0

Y como se publica debajo, 'hash()' de Python tiene ** exactamente ** la misma semántica que 'java.lang.Object.hashcode()'. –

Respuesta

70
id(x) 

hará el truco para usted. Pero tengo curiosidad, ¿qué pasa con el conjunto de objetos (que combina objetos por valor)?

Para su problema particular, probablemente mantendría el conjunto de identificadores o de objetos de envoltura. Un objeto contenedor contendrá una referencia y se comparará por x==y < ==>x.ref is y.ref.

También vale la pena señalar que los objetos Python también tienen una función hash. Esta función es necesaria para poner un objeto en un conjunto o diccionario. Se supone que a veces colisiona con diferentes objetos, aunque las buenas implementaciones de hash intentan hacerlo menos probable.

+1

Votar abajo, porque id (x) no se asegura de la unicidad para cada objeto. El OP tenía muy claro que desea tratar diferentes objetos que contienen el mismo valor para que sean * diferentes *. – Roy

+2

@ Roy por el contrario los [documentos] (https://docs.python.org/2/library/functions.html#id) dicen que 'id (x)' _is_ "garantiza ser único y constante para este objeto durante su vida útil ", lo que daría lugar a que diferentes objetos con el mismo valor tengan diferentes id (siempre que ambos existan al mismo tiempo) lo que permitiría al OP hacer lo que quisiera. – sparrowt

+0

@sparrowt Ya veo. Estoy de acuerdo con usted.El punto clave es que "el ID sea único * cuando dos objetos con el mismo valor coexistan *". 'id()' parece devolver el mismo ID para objetos creados repetidamente (y destruidos) con el mismo valor, de ahí mi comentario original, pero en realidad está bien aquí, porque OP indicó que los ID deben ser únicos cuando los objetos coexisten. Eliminando mi voto abajo. – Roy

18

Eso es para lo que "is" es para.

En lugar de pruebas "if a == b", que prueba para el mismo valor,

test "if a is b", que pondrá a prueba para el mismo identificador.

+17

¿Sería correcto decir que el "es" de Python es como "==" de Java y que "==" de Python es como "igual a()" de Java? – MatrixFrog

+9

@MatrixFrog Sí. – Imagist

1

Como ilya n menciona, id (x) produce un identificador único para un objeto.

Pero su pregunta es confusa, ya que el método hashCode de Java no proporciona un identificador único. El hashCode de Java funciona como la mayoría de las funciones hash: siempre devuelve el mismo valor para el mismo objeto, dos objetos que son iguales siempre obtienen códigos iguales, y los valores desiguales de hash implican códigos hash desiguales. En particular, dos objetos diferentes y desiguales pueden obtener el mismo valor.

Esto es confuso porque las funciones de hash criptográficas son bastante diferentes de esto, y más como (aunque no exactamente) la "identificación única" que usted solicitó.

El equivalente Python del método hashCode de Java es hash (x).

+0

Es por eso que mencioné explícitamente el método hashcode de java.lang.Object. Que, de forma predeterminada, produce un único largo para ese objeto. Me doy cuenta de que las otras implementaciones de hashcode pueden diferir, y lo hacen. – oneself

+0

Pero ese es el punto: hashCode no produce un único largo. Produce longs que intentan no colisionar, pero no puedes mapear cadenas a longs y producir un valor único. –

+1

... y viejo hilo que conozco. Pero sí quería señalar que id() es único solo cuando ambos objetos aún existen. Una vez liberado, la identificación se puede asignar a otro objeto por "Dos objetos con vidas no superpuestas pueden tener el mismo valor id()". [enlace] (https://docs.python.org/2/library/functions.html#id) –

-1

No tiene que comparar objetos antes de colocarlos en un conjunto. set() semántica ya se ocupa de esto.

class A(object): 
    a = 10 
    b = 20 
    def __hash__(self): 
     return hash((self.a, self.b)) 

    a1 = A() 
    a2 = A() 
    a3 = A() 
    a4 = a1 
    s = set([a1,a2,a3,a4]) 
    s 
=> set([<__main__.A object at 0x222a8c>, <__main__.A object at 0x220684>, <__main__.A object at 0x22045c>]) 

Nota: Usted realmente no tiene que anular de hash para demostrar este comportamiento :-)

+1

Su solución depende del tipo de clase que se hereda de: 'clase B (str): pase' si se llama con 'set ([B(), B()])' lleva a 'set ([''])'. La identificación de los diccionarios generalmente depende implícitamente de 'id (x)' para los objetos, solo debe usarla explícitamente y evitar casos en las esquinas. – Arne

+0

@ArneRecknagel tienes razón. pero, ¿qué pondrías en un conjunto después de marcar id (x)? – user942640

Cuestiones relacionadas