2011-12-21 8 views
6
class A(object): 

    def __init__(self, value): 
     self.value = value 

x = A(1) 
y = A(2) 

q = [x, y] 
q.remove(y) 

Quiero eliminar de la lista un objeto específico que se agregó antes y al que todavía tengo una referencia. No quiero una prueba de igualdad. Quiero una prueba de identidad. Este código parece funcionar tanto en CPython como en IronPython, pero ¿el lenguaje garantiza este comportamiento o solo es una casualidad?¿Es igual un objeto de Python que no anula los operadores de comparación?

La documentación del método list.remove es esto: same as del s[s.index(x)], lo que implica que se realiza una prueba de igualdad.

¿Un objeto será igual a sí mismo si no anula __cmp__, __eq__ o __ne__?

Respuesta

9

. En su ejemplo q.remove(y) eliminaría la primera aparición de un objeto que se compara con igual y. sin embargo, la forma en que se define la clase A, no debe tener una var iable compare igual con y - a excepción de cualquier otro nombre que también esté vinculado a la misma instancia y.

La sección pertinente de la documentación es here:

Si no se define ninguna operación __cmp__(), __eq__() or __ne__(), clase casos se comparan por la identidad del objeto ("dirección").

Así que la comparación para las instancias A es por identidad (implementada como dirección de memoria en CPython). Ningún otro objeto puede tener una identidad igual a id(y) durante la vida y 's, es decir, para el tiempo que se mantiene una referencia a y (que es necesario, si se va a quitarlo de una lista!)

Técnicamente, todavía es posible tener objetos en otras ubicaciones de memoria que están comparando igual - mock.ANY es un ejemplo. Pero estos objetos deben anular sus operadores de comparación para forzar el resultado.

+1

Curiosamente, el comportamiento parece ser el opuesto en Python 3 –

+1

'__cmp__' es [ido en Python 3] (https://docs.python.org/3.0/whatsnew/3.0.html#ordering-comparisons). Sin embargo, puedes lograr el mismo efecto usando '__eq__'. – wim

+0

Me preguntaba si no hay un __eq__ definido, ¿compara Python 3 por dirección? –

2

En python, un objeto siempre es igual a él (la única excepción que se me ocurre es float("nan"). Un objeto de una clase definida por el usuario no será igual a ningún otro objeto a menos que defina una función de comparación.

Ver también http://docs.python.org/reference/expressions.html#notin

0

La respuesta es sí y no.

consideremos el siguiente ejemplo

>>> class A(object): 
    def __init__(self, value): 
     self.value = value   
>>> x = A(1) 
>>> y = A(2) 
>>> z = A(3) 
>>> w = A(3) 
>>> q = [x, y,z] 
>>> id(y) #Second element in the list and y has the same reference 
46167248 
>>> id(q[1]) #Second element in the list and y has the same reference 
46167248 
>>> q.remove(y) #So it just compares the id and removes it 
>>> q 
[<__main__.A object at 0x02C19AB0>, <__main__.A object at 0x02C19B50>] 
>>> q.remove(w) #Fails because though z and w contain the same value yet they are different object 
Traceback (most recent call last): 
    File "<pyshell#11>", line 1, in <module> 
    q.remove(w) 
ValueError: list.remove(x): x not in list 

Se eliminará de la lista si y sólo si son el mismo objeto. Si son objetos diferentes con el mismo valor, no lo eliminarán.

+0

La respuesta es simplemente sí, no es "sí y no". Y el OP dijo explícitamente que querían una prueba de identidad, no una prueba de igualdad. – wim

Cuestiones relacionadas