[Tutor] "x and y" means "if x is false, then x, else y"??

Steven D'Aprano steve at pearwood.info
Mon Jul 5 15:18:47 CEST 2010


On Mon, 5 Jul 2010 07:37:12 pm Richard D. Moores wrote:
> On Mon, Jul 5, 2010 at 00:55, Steve Willoughby <steve at alchemy.com> 
wrote:
[...]
> Steve,
>
> Your answer seems very well-formulated. However, I've read it over
> and over, but I keep getting hung up over the meaning of "the return
> value" of an expression. I am of course familiar with values returned
> by a function, but don't quite grasp what the return value of, say,
> the y of "x and y" might mean.

At the risk of adding confusion by butting in (I'm also a Steve, just a 
different one...), perhaps a better expression would be just "the 
value" of an expression.

If you have any expression, such as:

23 + 42
"hello world".split()
len("abc")

then the expression has a value:

65
["hello", "world"]
3

That's what Steve means by "the return value".


> Also, you distinguish between a return value of True and and the
> value of y being such (say 5, and not 0) that it makes y true (but
> not True). So another  thing I need to know is the difference between
> True and true.  Also between False and false. And why the difference
> is important.

This is a fundamental part of Python's programming model: every object, 
without exception, can be used where some other languages insist on 
actual boolean flags. In Python, there's nothing special about True and 
False -- until version 2.3, they didn't even exist, and in fact they 
are implemented as a subclass of int. True is an alternative way of 
spelling 1, and False of 0:

>>> True*3
3
>>> False + 5
5

You can see more about the history of bool in Python here:
http://www.python.org/dev/peps/pep-0285/

Since Python allows direct boolean operations (if...else, and, or, not) 
on all objects, we need some rules for deciding what objects are 
considered True-like ("true") and which are considered False-like 
("false"). The distinction Python uses for built-ins is between 
something and nothing: an object which represents something is true, 
and one which represents nothing is false.

The most obvious example comes from numbers. Numbers which are equal to 
zero are obviously Nothing, and hence considered false. All other 
numbers are Something, and hence true.

Similarly for strings: the empty string is a string-flavoured Nothing, 
and all other strings are Something.

Collections -- lists, tuples and dicts -- are considered Nothing if they 
are empty, otherwise Something.

None is a special type of Nothing, and so is considered false.

When it comes to custom-built classes, rather than built-ins, the 
distinction may be a little weaker, since of course the programmer can 
define their class any way they like. Python first looks to see if the 
class has a __nonzero__ method, and if so, calls that. Otherwise it 
calls __len__. If the class has neither of those methods, it is 
automatically considered to be Something. So it's easy to create 
strange classes that don't quite fit into the Something/Nothing 
dichotomy:

class Funny:
    def __nonzero__(self):
        import time
        return time.time() % 2 == 0
        # true on even seconds, false on odd seconds

Python is quite happy to let you shoot yourself in the foot if you try.

Ruby has a similar policy, except in Ruby everything is true except for 
two objects: false and nil.

http://www.skorks.com/2009/09/true-false-and-nil-objects-in-ruby/

Other languages may make different choices.

In Python, True and False are merely the canonical true and false 
objects, and bool(x) will return the canonical Boolean value of x:

>>> bool(None)
False
>>> bool("something funny")
True

It is very rare you need to use bool. Don't write this:

if bool(x):
    ...

that's just a waste of a function call. It's *nearly* as silly as 
writing:

if (x==y) is True:  # Or should that be if (x==y) is True is True ?
    ...


> I'm thinking that possibly what would help would be to contextualize
> "x and y" in some snippet of code. I'm sorry to trouble you with my
> denseness.

s = some_string_value()
if not s:
    print "Empty string"
else:
    print "The string starts with", s[0]



people_with_red_hair = "Phil George Susan Samantha".split()
people_with_glasses = "Henry Felicity Michelle Mary-Anne Billy".split()
a = set(people_with_red_hair)
b = set(people_with_glasses)
if not a:
    print "There are no red-heads."
if not a.intersection(b):
    print "There are no red-heads who also wear glasses."




-- 
Steven D'Aprano


More information about the Tutor mailing list