integer >= 1 == True and integer.0 == False is bad, bad, bad!!!

Steven D'Aprano steve-REMOVE-THIS at cybersource.com.au
Mon Jul 12 23:51:06 EDT 2010


On Mon, 12 Jul 2010 17:36:38 -0700, Paul Rubin wrote:

>> I would argue against that. Why do you, the coder, care about the
>> specific details of treating ints in a boolean context? The int type
>> itself knows, leave the decision to it.
> 
> There is a horrible (IMO) thing that Perl, Lua, and Javascript all do,
> which is automatically convert strings to numbers, so "12"+3 = 15.
> Python has the good sense to throw a type error if you attempt such an
> addition, but it goes and converts various types to bool automatically,

No, what Python does is more subtle than that. An example using strings 
will (I hope!) make it clear. Or possibly muddy the waters even more.

Compare converting strings to ints: the string "1" maps to the int 1, "2" 
to 2, and so forth. There's a one-to-one map of string to int (modulo 
unicode and whitespace issues), and since this is more or less a 
universal standard, it's enshrined in the language.

Now consider converting strings to bools. Should "true" map to True? Or 
"yes", "ja", "vrai", "waar", or something else? That's an application-
specific question, not a universal standard (not even a de facto 
standard), and Python rightly avoids it.

What about "maybe" or "strawberry jam"? You can't convert "strawberry 
jam" into True or False any more than you can convert it into an int.

What Python does instead is to accept *any* object in a context where 
other languages (such as Pascal) would insist on a boolean. In practice, 
that means branches (if) as well as the short-cut operators and, or, not. 
The semantics of this is well-defined, and I trust I don't need to go 
over it again.

In an expression like:

x and y

unlike Pascal, there is no requirement that x and y be booleans. This is 
why I talk about x and y being used "in a boolean context", rather than 
converting it to a bool. [3,4,5] is not, by any stretch of the 
imagination, True converted into a list, and likewise [2,3,4] is a list 
and can't be converted to a flag any more than it can be converted to an 
int. But what I do say is that, according to Python's semantics, the list 
[3,4,5] is equivalent to True in a boolean context.

Where Python muddies the water is to provide a bool() built-in which 
*does* convert any object to canonical boolean form. bool([2,3,4]) 
returns True, which contradicts what I said above about not converting 
the list into a flag. I accept this -- it's a triumph of practicality 
over purity. It would be silly to force people to write:

# get the canonical form
if any_old_object:
    flag = True
else:
    flag = False

when we can say flag = bool(any_old_object).

One last thing -- we can see that Python does *not* convert objects to 
bools "in a boolean context". The Python virtual machine really does 
accept any object as an argument to and/or/not operators, as well as if:

>>> import dis
>>> dis.dis(compile('a or b', '', 'single'))
  1           0 LOAD_NAME                0 (a)
              3 JUMP_IF_TRUE             4 (to 10)
              6 POP_TOP
              7 LOAD_NAME                1 (b)
        >>   10 PRINT_EXPR
             11 LOAD_CONST               0 (None)
             14 RETURN_VALUE


The JUMP_IF_TRUE opcode accepts any object, not just True or False.



-- 
Steven



More information about the Python-list mailing list