Operator Precedence/Boolean Logic

Chris Angelico rosuav at gmail.com
Sat Jul 16 13:06:42 EDT 2016


On Sun, Jul 17, 2016 at 2:27 AM, Steven D'Aprano <steve at pearwood.info> wrote:
> If you really mean your words, and don't wish to step back and make a less
> extreme claim, then you ought to be easily able to show that Python's use
> of bools hardly ever works. It's clearly a terrible idea, almost every use
> of it is a failure, even Blind Freddy can see that it is hard to use and
> not straightforward.

Anecdotal, yet important, factoid: When I teach Python to people
who've come from other languages, I explain it as: "In Python,
anything that represents emptiness is false. Everything else is
true.". So far, not a single student has failed to understand this,
and quite a few have thanked me for the simplicity (as if it's
credited to me, rather than just being a reflection of Python's
reality).

> The truthiness API is straightforward. Any value or object is usable in a
> boolean context, and there is a well-defined protocol for deciding whether
> arbitrary objects are considered true or false:
>
> * If the class defined a __nonzero__ (or __bool__ in Python 3) method, then
> the truthiness of the object is given by the result of calling that method.
>
> * If there is no __nonzero__ (or __bool__) method, but the class defines
> __len__, which returns zero, then the object is deemed falsey, otherwise it
> is deemed to be truthy.
>
> * If the class lacks both dunder methods, then the object is deemed truthy.

This isn't how truthiness is generally understood, though. Do you
explain to someone that (1).__bool__() returns True, or do you simply
say that 1, being a non-zero number, is true?

> But that doesn't mean that every imaginable class trivially maps into that
> dichotomy. Suppose we create a tri-state logic class, with three states
> Yes, No and Maybe. Obviously Yes should map to True, and No to False. What
> should Maybe map to? We may spend many sleepless hours weighing up the pros
> and cons of mapping Maybe to True versus Maybe to False. Or we might flip a
> coin.

Maybe can also raise an exception in __bool__ if it likes. Or, to
emphasize the tri-state nature of your logic class, *all* your
instances could raise, with a message saying that "if x:" should be
"if x >= tri.Maybe:" or "if x is tried.and.True" depending on how you
want to handle Maybe.

Ultimately, though, computers don't work with Maybes. They work with
concrete yes/no answers: should I run this code or not? (In
assembly/machine language, probably "should I take this jump or not"
covers it all.) Somewhere along the way, you have to turn that Maybe
in to either True or False, and that should be *before* you're asking
the question "if x:". Perhaps "Maybe" really means "Inherit" (as in
the DeScribe style sheet system; you have a tree of styles, and a
style could say "Bold: True" or "Bold: False", but if it doesn't, it's
shown as "Bold: Maybe" but really means "Bold: Same as parent"), in
which case you resolve it with "while x == tri.Maybe: x =
self.parent.x" before doing the lookups. Or perhaps Maybe means "the
user didn't enter a value", in which case you go with some global
default. Or perhaps it means "the data is too borderline to call this
one", in which case you flip a coin. Actual physical coin, mind, no
simulations here!

> And yes, Rustom, I'm very familiar with the philosophical objections to the
> something/nothing distinction. "Is zero truly nothing, or is it some thing
> distinct from the absence of any number?" I'm not interested in that
> argument. Let the philosophers count angels, but as far as Python code
> goes, I'm an intuitionist: if I have zero sheep, that's the same as not
> having any sheep, or having no sheep.
>
> I'm more sympathetic to the view that an empty list is different from
> absence of a list, therefore it's something, not nothing. Fine, if that's
> the way you want to reason, go right ahead and do so when you write your
> own language. But in Python, practicality wins, and empty sequences and
> collections are treated as "nothing". (It's a metaphor, not a deep
> philosophical axiom.)

Pike took the opposite view - an empty array is still true. Did you
put up a new shopping list? Yes, there's a list there, even though
it's currently empty. Both make sense, and both languages have very
simple definitions of "this is true, that is false". (And both permit
user-defined types to choose whether they're truthy or falsey, so of
course someone somewhere has made a pathological case, guaranteed.)
Python says that having zero sheep is the same as not having any
sheep; Pike says that a box of doughnuts is still a box even when
you've eaten all the doughnuts.

Most importantly, neither of them is "bizarre". (In most practical
usage, it actually works out pretty much the same way.) Rustom, I
await evidence from you that (a) new Python programmers are massively
confused because of the boolification rules, or (b) transitioning
programmers (new to Python but with experience in some other language)
are confused, or (c) that this is more of a bug magnet than comparable
features, while providing less useful functionality. Go! Prove to us.

ChrisA



More information about the Python-list mailing list