Crosstips.org

My fun Crossword solver project. Crosstips.org & Krysstips.se

Kung Fu

Fujian White Crane Kung Fu

Fry-IT

Fry-IT is the company I work for

Photos

Photoalbum, both old and new.

Zope

What I have and am doing with Zope

Receptsamlingen

In Swedish only. About my "Collection of Recipes" website.

Contact me

My contact details and how to contact me.

 

KungFuPeople.com
Do you train Kung Fu?
Or know someone who does?
Then check out KungFuPeople.com


Mobile version of this page Mobile version of this page


 

bool is instance of int in Python


4th of December 2008

I lost about half an hour just moments ago debugging this and pulling out a fair amount of hair. I had some code that looked like this:

 result = []
 for key, value in data.items():
    if isinstance(value, int):
        result.append(dict(name=key, value=value, type='int'))
    elif isinstance(value, float):
        result.append(dict(name=key, value=value, type='float'))
    elif isinstance(value, bool):
        result.append(dict(name=key, type='bool',
                           value=value and 'true' or 'false'))
 ...

It looked so simple but further up the tree I never got any entries with type="bool" even though I knew there were boolean values in the dictionary.

The pitfall I fell into was this:

 >>> isinstance(True, bool)
 True
 >>> isinstance(False, bool)
 True
 >>> isinstance(True, int)
 True
 >>> isinstance(False, int)
 True

Not entirely obvious if you ask me. The solution in my case was just to change the order of the if and the elif so that bool is tested first.



Comment

Steve Holden - 4th December 2008  [«« Reply to this]
It is indeed kind of warty.

Presumably you already knew about this:

>>> d = {(3.0 +0j): "something"}
>>> d[3]
'something'
>>>

The Boolean behavior is similar, though slightly different. This was not one of Guido's best ideas - *and* it was introduced in a minor release!
thp - 4th December 2008  [«« Reply to this]
Is this the case in Python 3000 as well? Seems like a bad design decision that might have been changed ;)
dman~@~dman13_dot_dyndns_dot_org - 5th December 2008  [«« Reply to this]
It is perfectly logical, if you were around when the bool type was added to python (sometime around 2.2 or 2.3).

Prior to introduction of an actual bool type, 0 and 1 were the official representation for truth value, similar to C89. To avoid unnecessarily breaking non-ideal but working code, the new bool type needed to work just like 0 and 1. This goes beyond merely truth value, but all integral operations. No one would recommend using a boolean result in a numeric context, nor would most people recommend testing equality to determine truth value, no one wanted to find out the hard way just how much existing code is that way. Thus the decision to make True and False masquerade as 1 and 0, respectively. This is merely a historical artifact of the linguistic evolution.

In fact, give this a try:

>>> True == 1
True
>>> True == 0
False
>>> False == 0
True
>>> False == 1
False
>>> True + 2
3
>>> False - 5
-5

@thp: Good point. This is something python3 should have corrected while the opportunity presented itself.
Peter Bengtsson - 5th December 2008   [«« Reply to this]
Good point about the backward compatibility issue. It was never going to be easy. I'll let this one slide. However it would have been nice to have that fixed for py3
Jason - 5th December 2008  [«« Reply to this]
Interesting, looks like bool is a subtype of int.

>>> bool.mro()
[<type 'bool'>, <type 'int'>, <type 'object'>]
Andrew Veitch - 6th December 2008  [«« Reply to this]
I would use:

if type(value) is bool:
elseif type(value) is int:
elseif type(value) is float:

which will work as expected.
Peter Bengtsson - 8th December 2008   [«« Reply to this]
I like that one! It looks neat and pythonic. Maybe I should stop using isinstance() for basic types and use that weapon more around custom classes and instance objects.
Wallacoloo - 22nd March 2010  [«« Reply to this]
result.append(dict(name=key, type=type(value), value=value))
if isinstance(value, bool):
result[-1]['value'] = ("false", "true")[value]
 
Name:
Email:
hide my email address.

Your email address will be encoded to prevent email-extraction spiders from reading it so you won't get spammed if you decide to show your email address.