Comparando booleano e int usando isinstance

¿Alguien puede darme una explicación de por qué isinstance() devuelve True en el siguiente caso? Esperaba Falso, al escribir el código.

 print isinstance(True, (float, int)) True 

Mi conjetura sería que las subclases internas de Python, como cero y uno, ya sean flotantes o int, ambas se evalúan cuando se usan como booleanos, pero no se sabe la razón exacta.

¿Cuál sería la forma más pythonica de resolver tal situación? Podría usar type() pero en la mayoría de los casos esto se considera menos pythonic.

Por razones históricas, bool es una subclase de int , por lo que True es una instancia de int . (Originalmente, Python no tenía un tipo de bool, y las cosas que devolvían valores de verdad devolvían 1 o 0. Cuando agregaban bool , True y False tenían que ser reemplazos directos para 1 y 0 tanto como fuera posible para la compatibilidad con versiones anteriores, por lo tanto, la subclase .)

La forma correcta de “resolver” esto depende exactamente de lo que considera el problema.

  • Si quieres que True deje de ser un int , bueno, muy mal. Eso no va a suceder.
  • Si desea detectar valores booleanos y manejarlos de manera diferente a otros bashs, puede hacerlo:

     if isinstance(whatever, bool): # special handling elif isinstance(whatever, (float, int)): # other handling 
  • Si desea detectar objetos cuya clase específica es exactamente float o int , rechazando subclases, puede hacerlo:

     if type(whatever) in (float, int): # Do stuff. 
  • Si quieres detectar todas las flotaciones y entradas, ya lo estás haciendo.

Sí, esto es correcto, es una subclase de int, puede verificarlo utilizando el intérprete:

 >>> int.__subclasses__() [] 

Si solo quieres verificar int :

 if type(some_var) is int: return True else: return False 

Vea algunos comportamientos (no tan extraños) de python en bool y int

 >>> 1 == True True >>> 0 == False True >>> True*5 == 0 False >>> True*5 == 5 True >>> 

¡Cuán intercambiables pueden ser usados ​​…!

Desde boolobject.h (win py 2.7) puedo ver un typedef de int para bool obj. Así que es bastante evidente que bool ha heredado algunas características faciales de int.

 #ifndef Py_BOOLOBJECT_H #define Py_BOOLOBJECT_H #ifdef __cplusplus extern "C" { #endif typedef PyIntObject PyBoolObject;