Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

219
Views
¿Por qué `if None.__eq__("a")` parece evaluarse como True (pero no del todo)?

Si ejecuta la siguiente declaración en Python 3.7, (de mi prueba) imprimirá b :

 if None.__eq__("a"): print("b")

Sin embargo, None.__eq__("a") se evalúa como NotImplemented .

Naturalmente, "a".__eq__("a") se evalúa como True , y "b".__eq__("a") se evalúa como False .

Inicialmente descubrí esto al probar el valor de retorno de una función, pero no devolví nada en el segundo caso, por lo que la función devolvió None .

¿Que está pasando aqui?

over 4 years ago · Santiago Trujillo
3 answers
Answer question

0

Este es un gran ejemplo de por qué los métodos __dunder__ no deben usarse directamente, ya que a menudo no son reemplazos apropiados para sus operadores equivalentes; en su lugar, debe usar el operador == para comparaciones de igualdad, o en este caso especial, al verificar None , use is (salte al final de la respuesta para obtener más información).

Has hecho

 None.__eq__('a') # NotImplemented

Que devuelve NotImplemented ya que los tipos que se comparan son diferentes. Considere otro ejemplo en el que dos objetos con diferentes tipos se comparan de esta manera, como 1 y 'a' . Hacer (1).__eq__('a') tampoco es correcto y devolverá NotImplemented . La forma correcta de comparar estos dos valores para la igualdad sería

 1 == 'a' # False

Lo que pasa aquí es

  1. Primero, se prueba (1).__eq__('a') , que devuelve NotImplemented . Esto indica que la operación no es compatible, por lo que
  2. Se llama 'a'.__eq__(1) , que también devuelve el mismo NotImplemented . Asi que,
  3. Los objetos se tratan como si no fueran iguales y se devuelve False .

Aquí hay un pequeño y agradable MCVE que usa algunas clases personalizadas para ilustrar cómo sucede esto:

 class A: def __eq__(self, other): print('A.__eq__') return NotImplemented class B: def __eq__(self, other): print('B.__eq__') return NotImplemented class C: def __eq__(self, other): print('C.__eq__') return True a = A() b = B() c = C() print(a == b) # A.__eq__ # B.__eq__ # False print(a == c) # A.__eq__ # C.__eq__ # True print(c == a) # C.__eq__ # True

Por supuesto, eso no explica por qué la operación devuelve verdadero. Esto se debe a que NotImplemented es en realidad un valor real:

 bool(None.__eq__("a")) # True

Igual que,

 bool(NotImplemented) # True

Para obtener más información sobre qué valores se consideran verdaderos y falsos, consulte la sección de documentos sobre Pruebas de valor de verdad , así como esta respuesta . Vale la pena señalar aquí que NotImplemented es cierto, pero habría sido una historia diferente si la clase hubiera definido un método __bool__ o __len__ que devolviera False o 0 respectivamente.


Si desea el equivalente funcional del operador == , use operator.eq :

 import operator operator.eq(1, 'a') # False

Sin embargo, como se mencionó anteriormente, para este escenario específico , donde está verificando None , el uso is :

 var = 'a' var is None # False var2 = None var2 is None # True

El equivalente funcional de esto es usar operator.is_ :

 operator.is_(var2, None) # True

None es un objeto especial y solo existe 1 versión en la memoria en cualquier momento. IOW, es el único singleton de la clase NoneType (pero el mismo objeto puede tener cualquier número de referencias). Las pautas de PEP8 lo hacen explícito:

Las comparaciones con singletons como None siempre deben hacerse con is o is not , nunca con los operadores de igualdad.

En resumen, para singletons como None , una verificación de referencia con is es más apropiada, aunque tanto == como is funcionarán bien.

over 4 years ago · Santiago Trujillo Report

0

El resultado que está viendo es causado por el hecho de que

 None.__eq__("a") # evaluates to NotImplemented

se evalúa como NotImplemented , y el valor de verdad de NotImplemented se documenta como True :

https://docs.python.org/3/library/constants.html

Valor especial que deben devolver los métodos especiales binarios (por ejemplo, __eq__() , __lt__() , __add__() , __rsub__() , etc.) para indicar que la operación no está implementada con respecto al otro tipo; puede ser devuelto por los métodos especiales binarios en el lugar (por ejemplo, __imul__() , __iand__() , etc.) para el mismo propósito. Su valor de verdad es verdadero.

Si llama al __eq()__ manualmente en lugar de solo usar == , debe estar preparado para lidiar con la posibilidad de que devuelva NotImplemented y que su valor de verdad sea verdadero.

over 4 years ago · Santiago Trujillo Report

0

Como ya pensó que None.__eq__("a") se evalúa como NotImplemented sin embargo, si intenta algo como

 if NotImplemented: print("Yes") else: print("No")

el resultado es

sí

esto significa que el valor de verdad de NotImplemented true

Por lo tanto, el resultado de la pregunta es obvio:

None.__eq__(something) produce NotImplemented

Y bool(NotImplemented) evalúa como True

Entonces, if None.__eq__("a") es siempre True

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!