Estoy confundido acerca de cómo funciona el operador == en Python 3. De docs, eq(a, b) es equivalente a a == b. También eq y __eq__ son equivalentes.

Tome el siguiente ejemplo:

class Potato:
    def __eq__(self, other):
        print("In Potato's __eq__")
        return True

>> p = Potato()
>> p == "hello"
In Potato's __eq__ # As expected, p.__eq__("hello") is called
True
>> "hello" == p
In Potato's __eq__ # Hmm, I expected this to be false because
True               # this should call "hello".__eq__(p)
>> "hello".__eq__(p)
NotImplemented     # Not implemented? How does == work for strings then?

Editar: No renuncies a la programación después de solo dos horas. Escribir código a menudo significa escribir durante una hora y depurar durante varias horas. Una de las mejores formas de depurar es escribir el código lo más mínimo posible. Por ejemplo, intente reproducir su error usando mi ejemplo mínimo anterior. (

Estoy buscando el algoritmo general que se emplea para la igualdad ... La mayoría, si no todas las demás respuestas SO, se refieren a reglas de coerción, que ya no se aplican en Python 3.

2
plafer 30 jun. 2017 a las 01:43

3 respuestas

La mejor respuesta

Está mezclando las funciones en el módulo operator y los métodos utilizados para implementar esos operadores. operator.eq(a, b) es equivalente a a == b o operator.__eq__(a, b), pero no a a.__eq__(b).

En términos del método __eq__, == y operator.eq funcionan de la siguiente manera:

def eq(a, b):
    if type(a) is not type(b) and issubclass(type(b), type(a)):
        # Give type(b) priority
        a, b = b, a

    result = a.__eq__(b)
    if result is NotImplemented:
        result = b.__eq__(a)
    if result is NotImplemented:
        result = a is b
    return result

Con la advertencia de que el código real realiza la búsqueda de métodos para __eq__ de una manera que omite los dictados de instancias y los métodos personalizados __getattribute__ / __getattr__.

7
user2357112 supports Monica 29 jun. 2017 a las 22:51

Al hacer esto:

"hello" == potato

Python primero llama "hello".__eq__(potato). Ese retorno NotImplemented, por lo que Python lo prueba con el otro forma: potato.__eq__("hello").

Devolver NotImplemented no significa que no haya implementación de .__eq__ en ese objeto. Significa que la implementación no sabía cómo comparar con el valor que se pasó. De https://docs.python.org/3/library/constants.html#NotImplemented:

Nota Cuando un método binario (o in situ) devuelve NotImplemented, el intérprete intentará la operación reflejada en el otro tipo (o en algún otro recurso alternativo, según el operador). Si todos los intentos devuelven NotImplemented, el intérprete generará una excepción apropiada. Si devuelve NotImplemented incorrectamente, se generará un mensaje de error engañoso o se devolverá el valor NotImplemented al código Python. Consulte Implementación de operaciones aritméticas para ver ejemplos.

3
user94559 29 jun. 2017 a las 22:48

Estoy confundido acerca de cómo funciona el operador == en Python 3. De los documentos, eq(a, b) es equivalente a a == b. También eq y __eq__ son equivalentes.

No, ese es solo el caso en el módulo operator . El módulo de operador se utiliza para pasar un == como una función , por ejemplo. Pero operator no tiene mucho que ver con Python vainilla en sí.

editar: No renuncies a la programación después de solo dos horas. Escribir código a menudo significa escribir durante una hora y depurar durante varias horas. Una de las mejores formas de depurar es escribir el código lo más mínimo posible. Por ejemplo, intente reproducir su error usando mi ejemplo mínimo anterior. (

En Python todo es un objeto: un int es un objeto, una "clase" es un objeto ", un None es un objeto, etc. Podemos, por ejemplo, obtener el __eq__ de 0:

>>> (0).__eq__
<method-wrapper '__eq__' of int object at 0x55a81fd3a480>

Entonces la igualdad se implementa en la clase "int". Como se especifica en la documentación sobre el modelo de datos __eq__ puede devolver varios valores: True, False pero cualquier otro objeto (para el cual se calculará la veracidad ). Si, por otro lado, se devuelve NotImplemented, Python recurrirá y llamará al objeto __eq__ en el objeto en el otro lado de la ecuación.

1
Willem Van Onsem 29 jun. 2017 a las 22:51