print - Si escribe pato en Python, ¿debería probar la instancia?
type python 3 (3)
Tienes una clase de Python que necesita una prueba de iguales. Python debería usar tipografía de pato pero, ¿es (mejor / más preciso) incluir o excluir una prueba de instancia en la función eq ? Por ejemplo:
class Trout(object):
def __init__(self, value):
self.value = value
def __eq__(self, other):
return isinstance(other, Trout) and self.value == other.value
El principio de "tipificación de pato" es que no te importa qué es other , siempre que tenga un atributo de value . Entonces, a menos que sus atributos compartan nombres con semánticas en conflicto, sugeriría hacerlo así:
def __eq__(self, other):
try:
return self.value == other.value
except AttributeError:
return False # or whatever
(Alternativamente, puede probar si other tiene un atributo de value , pero "es más fácil pedir perdón que obtener permiso")
El uso de isintsance() generalmente está bien en los __eq__() . Sin embargo, no debe devolver False inmediatamente si falla la comprobación de isinstance() ; es mejor devolver NotImplemented para dar a other.__eq__() posibilidad de ser ejecutado:
def __eq__(self, other):
if isinstance(other, Trout):
return self.x == other.x
return NotImplemented
Esto será particularmente importante en las jerarquías de clases donde más de una clase define __eq__() :
class A(object):
def __init__(self, x):
self.x = x
def __eq__(self, other):
if isinstance(other, A):
return self.x == other.x
return NotImplemented
class B(A):
def __init__(self, x, y):
A.__init__(self, x)
self.y = y
def __eq__(self, other):
if isinstance(other, B):
return self.x, self.y == other.x, other.y
return NotImplemented
Si regresara False inmediatamente, como lo hizo en su código original, perdería la simetría entre A(3) == B(3, 4) y B(3, 4) == A(3) .
Usar isinstance en los métodos __eq__ es bastante común. La razón de esto es que si el método __eq__ falla, puede __eq__ un método __eq__ desde otro objeto. La mayoría de los métodos normales se llaman explícitamente, pero __eq__ se llama implícitamente, por lo que se requiere mirar antes de saltar con más frecuencia.
EDITAR (gracias por el recordatorio, Sven Marnach):
Para hacer que sea alternativo, puede devolver el singleton No implementado, como en este ejemplo:
class Trout(object):
def __init__(self, value):
self.value = value
def __eq__(self, other):
if isinstance(other, Trout):
return self.value == other.value
else:
return NotImplemented
Supongamos que una RainbowTrout sabe cómo compararse con una Trout o con otra RainbowTrout , pero una Trout solo sabe cómo compararse con una Trout . En este ejemplo, si prueba mytrout == myrainbowtrout , Python llamará primero mytrout.__eq__(myrainbowtrout) , notará que falla, y luego llamará a myrainbowtrout.__eq__(mytrout) , lo cual myrainbowtrout.__eq__(mytrout) .