[Tutor] While truth

Steven D'Aprano steve at pearwood.info
Tue May 20 14:46:23 CEST 2014


On Tue, May 20, 2014 at 08:25:48AM +0000, Ian D wrote:

> I was reading a tutorial that had these examples in it:
> 
> >>> while False:
> 
>   print("False is the new True.")

[... snip examples ...]


> I was wondering if the gist of a while statement could be explained in 
> the context of these examples.
> 
> e.g. while False:
> 
> means while True is False, which is never True because True is of 
> course True not False.
> 
> but while 6:
> 
> means..... err while 6 is True? and this is True because... err.


Not quite "6 is True", except figuratively speaking.

It might be easier to consider if...else rather than while, although the 
rules are exactly the same. An if...else block looks at a value, and 
then decides which branch to take: the "if" part or the "else" part. So 
we might have something like:

if condition:
    do_this()
else:
    do_that()


While-loops are similar, except that they repeat so long as the 
condition is a true value, rather than just once.

while condition:
    do_this()


Now, why did I say "the condition is a true value" instead of "the 
condition is True"? To explain, let me contrast Python with some other 
programming languages.

In some programming languages, the condition in an if or while statement 
is restricted to one of exactly two values, usually called True and 
False. These values are called "Booleans" (named after the mathematician 
who first worked on them, George Boole) or just "bools". Any other 
value, like 6, or None, or "Hello World", is an error. In those 
languages, "if condition" will take one branch if condition is True, and 
the other branch if False, and there are no other possibilities:

if condition:
    print("condition is True")
else:
    print("condition is False")


*Python is not like this.*

In languages like Python, the value being tested can have many different 
values. We can describe this in various ways:

# This is what Python does.
if condition:
    print("condition is a truthy value")
    print("condition is true-ish")
    print("in a boolean context, condition is true")
    print("condition is something")
else:
    print("condition is a falsey value")
    print("condition is false-ish")
    print("in a boolean context, condition is false")
    print("condition is nothing")


Think of this as "duck-typing for bools". Most of the time, we don't 
care if condition is *actually* True or False, only whether it is 
true-like or false-like. Many other languages do something similar to 
this, e.g. Javascript, PHP, Ruby, and so on.

Notice that I use (big T) True and (big F) False to refer to the actual 
Python constants True and False, and (small t) true and (small f) false 
to refer to things which are truthy or falsey.

Back to our if...else statement, or while statement: the condition 
doesn't have to be an actual bool True or False, it can be any value at 
all. Try running this bit of code and see what it prints:


for condition in ("Hello World", 23, [], "", None, 1.5, 0.0, [1, 2, 3]):
    if condition:
        print("%r is a truthy value" % condition)
    else:
        print("%r is a falsey value" % condition)


Can you see the pattern? I suggest you run the above before reading on. 
Don't worry, I'll wait... 

W
E
 
A
R
E
 
W
A
I
T
I
N
G

Can you see the pattern?

In Python, values which represent "something" are considered truthy. 
Those which represent "nothing" or "empty" are considered falsey. So we 
have:

Falsey values:
  None
  0
  0.0
  empty string ""
  empty list []
  empty tuple ()
  empty dict {}
  and of course False

Truthy values:
    any non-zero integer, like 1, 2, -3, ...
    any non-zero float, like 2.5, 17.8, -100.1, ...
    any non-empty string, like "spam", "eggs", ...
    any non-empty list, like [1, 2, 3]
    any non-empty tuple, like (0, 1)
    any non-empty dict, like {23: "twenty-three"}
    and of course True


99% of the time, you shouldn't care whether something is actually True 
or False. Well, perhaps 90% of the time. But, if you do care, you can 
convert any object you like to True or False by calling bool() on it:

bool(None)
=> returns False, because None is falsey

bool(101)
=> returns True, because 101 is truthy


What do you think bool("False") will return?

Since it's a string, and it is not the empty string "", it will return 
True. If you need to convert the string "False" to False, you need to 
test for it yourself.

A few words of advice. Never write something like this:

while bool(value):
    ...

since the call to bool() is redundant. Python already checks to see 
whether value is truthy, calling bool() just does it twice.

But even worse is this:

while bool(value) is True:
    ...


That just displays unfamiliarity with boolean logic and makes you look 
ignorant. bool(value) will return True or False, so comparing it to True 
is redundant. If you don't trust that, where do you stop?

while bool(value): ...
while bool(value) is True: ...
while (bool(value) is True) is True: ...
while ((bool(value) is True) is True) is True: ...
while (((bool(value) is True) is True) is True) is True: ...
while ((((bool(value) is True) is True) is True) is True) is True: ...
while (((((bool(value) is True) is True) is True) is True) is True) is True: ...




-- 
Steven


More information about the Tutor mailing list