Search code examples
pythonintbooleancomparisonisinstance

Comparing boolean and int using isinstance


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.


Solution

  • 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.