Python, сравнивающий boolean и int с использованием isinstance

Может ли кто-нибудь объяснить мне, почему isinstance() возвращает True в следующем случае? Я ожидал False, когда писал код.

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

Мое предположение заключалось бы в том, что его внутренний подкласмент python, как ноль, так и один - float float или int - оба оцениваются при использовании в качестве логического, но не знают точной причины.

Каким будет самый питонический способ решить такую ​​ситуацию? Я мог бы использовать type(), но в большинстве случаев это считается менее pythonic.

Ответ 1

По историческим причинам bool является подклассом int, поэтому True является экземпляром int. (Первоначально Python не имел типа bool, а возвращаемые значения истинности возвращались 1 или 0. Когда они добавили bool, True и False имели для замены на 1 и 0 как можно больше для обратной совместимости, следовательно, для подкласса.)

Правильный способ "решить" это зависит от того, что вы считаете проблемой.

  • Если вы хотите True перестать быть int, ну, слишком плохо. Это не произойдет.
  • Если вы хотите обнаружить логические значения и обрабатывать их по-другому от других int, вы можете сделать это:

    if isinstance(whatever, bool):
        # special handling
    elif isinstance(whatever, (float, int)):
        # other handling
    
  • Если вы хотите обнаружить объекты, чей конкретный класс точно равен float или int, отклоняя подклассы, вы можете сделать это:

    if type(whatever) in (float, int):
        # Do stuff.
    
  • Если вы хотите обнаружить все поплавки и ints, вы уже это делаете.

Ответ 2

Если вы хотите проверить только int:

if type(some_var) is int:
    return True

else:
    return False

Ответ 3

Да, это правильно, это подкласс int, вы можете проверить его с помощью интерпретатора:

>>> int.__subclasses__()
[<type 'bool'>]

Ответ 4

Посмотрите некоторые поведения (не так странно) Python на Bool и Int

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

Как взаимозаменяемы они могут быть использованы...!

Из boolobject.h(win py 2.7) я вижу typedef для bool obj. Так что довольно очевидно, что bool унаследовал несколько черт лица int.

#ifndef Py_BOOLOBJECT_H
#define Py_BOOLOBJECT_H
#ifdef __cplusplus
extern "C" {
#endif


typedef PyIntObject PyBoolObject;