Comparing boolean and int using isinstance

PythonIntBooleanComparisonIsinstance

Python Problem Overview


Can someone give me an explanation why isinstance() returns True in the following case? I expected False, when writing the code.

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

My guess would be that its Python's internal subclassing, as zero and one - whether float or int - both evaluate when used as boolean, but don't know the exact reason.

What would be the most pythonic way to solve such a situation? I could use type() but in most cases this is considered less pythonic.

Python Solutions


Solution 1 - Python

For historic reasons, bool is a subclass of int, so True is an instance of int. (Originally, Python had no bool type, and things that returned truth values returned 1 or 0. When they added bool, True and False had to be drop-in replacements for 1 and 0 as much as possible for backward compatibility, hence the subclassing.)

The correct way to "solve" this depends on exactly what you consider the problem to be.

  • If you want True to stop being an int, well, too bad. That's not going to happen.

  • If you want to detect booleans and handle them differently from other ints, you can do that:

      if isinstance(whatever, bool):
          # special handling
      elif isinstance(whatever, (float, int)):
          # other handling
    
  • If you want to detect objects whose specific class is exactly float or int, rejecting subclasses, you can do that:

      if type(whatever) in (float, int):
          # Do stuff.
    
  • If you want to detect all floats and ints, you're already doing that.

Solution 2 - Python

Yes, this is right, it's a subclass of int, you can verify it using the interpreter:

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

Solution 3 - Python

You can see the method resolution order, and find all superclasses from there:

>>> bool.__mro__
(<class 'bool'>, <class 'int'>, <class 'object'>)

Solution 4 - Python

If you only want to check for int:

if type(some_var) is int:
    return True

else:
    return False

Solution 5 - Python

See some behaviors (Not so wierd) of python on bool and int

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

How interchangeable can they be used...!

From boolobject.h (win py 2.7) I can see a typedef of int for bool obj. So it is pretty evident that bool has inherited few facial features of int.

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


typedef PyIntObject PyBoolObject;

Solution 6 - Python

Here is a instance checker that is safe with bool's and takes single types or tuples of types just like isinstance()

def isInst(o, of) -> bool:
    if o is None: return False
    cls = o.__class__
    if isinstance(of, type):
        return cls == of

    else:
        if cls == bool:
            return bool in of
        else:
            for i in range(len(of)):
                if cls == of[i]: return True

    return False

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionjake77View Question on Stackoverflow
Solution 1 - Pythonuser2357112View Answer on Stackoverflow
Solution 2 - PythonsbzView Answer on Stackoverflow
Solution 3 - PythonVicrobotView Answer on Stackoverflow
Solution 4 - PythonEyal LevinView Answer on Stackoverflow
Solution 5 - PythonVenfah NazirView Answer on Stackoverflow
Solution 6 - PythonTimothy C. QuinnView Answer on Stackoverflow