Comparisons and sorting of a numeric class....

Steven D'Aprano steve+comp.lang.python at
Thu Jan 8 00:46:03 CET 2015

Marko Rauhamaa wrote:

> Steven D'Aprano <steve at>:
>> int 0 is a falsey object
>> NoneType None is a falsey object
>> str 'hello' is a truthy object
>> float 23.0 is a truthy object
> I prefer the Scheme way:
>    #f is a falsey object
>    everything else is a truthy object

The Scheme way has no underlying model of what truthiness represents, just
an arbitrary choice to make a single value have one truthiness, and
everything else the other. It's just as meaningless and just as arbitrary
as the opposite would be:

    #t is True
    everything else is falsey

In both cases, you have the vast infinity of values apart from #f (or #t, as
the case may be) which are indistinguishable from each other under the
operation of "use in a boolean context". In other words, apart from #f or
#t, bool(x) maps everything to a single value. That makes it useless for
anything except distinguishing #f (or #t) from "everything else".

(I'm mixing scheme and python here, but I trust my meaning is clear.)

Given x of some type other than the Boolean type, bool(x) always gives the
same result. Since all non-Booleans are indistinguishable under that
operation, it is pointless to apply that operation to them.

I'd rather the Pascal way:

    #t is True
    #f is False
    everything else is an error

That at least gives you the benefits (if any) of strongly-typed bools.

Python has a (mostly) consistent model for truthiness: truthy values
represent "something", falsey values represent "nothing" or emptiness:

Falsey values:
  Numeric zeroes: 0, 0.0, 0j, Decimal(0), Fraction(0)
  Empty strings '', u''
  Empty containers [], (), {}, set(), frozenset()

Truthy values:
  Numeric non-zeroes
  Non-empty strings
  Non-empty containers
  Any other arbitrary object

The model isn't quite perfect (I don't believe any model using truthiness
can be) but the number of gotchas in the built-ins and standard library are
very small. I can only think of two:

- datetime.time(0) is falsey. Why midnight should be falsey is an 
  accident of implementation: datetime.time objects inherit from 
  int, and midnight happens to be represented by zero seconds.

- Empty iterators are truthy. Since in general you can't tell in 
  advance whether an iterator will be empty or not until you try 
  it, this makes sense.


More information about the Python-list mailing list