simultaneous assignment

Steve R. Hastings steve at hastings.org
Tue May 2 14:46:42 EDT 2006


On Tue, 02 May 2006 17:15:05 +0000, John Salerno wrote:
> Basically W, X, Y and Z are propositions 
> that are either true or false, and the puzzle lists a few statements 
> such as "Exactly one of X, Y and Z is true", and I'm trying to work out 
> a little algorithm that might test for this kind of stuff.

Okay.  You don't need to worry about the "is" tests at all.


Python always represents the value "True" with a reference to a True
object, and likewise "False" is a reference to a False object.  To save
memory, Python has just one of each object, so:

a = False
b = False
a is b  # this will always be true


As some other posters showed by example, but didn't really explain, Python
will *sometimes* but not always reuse integer objects.  For common integer
values such as 0 and 1, Python will reuse the objects; for uncommon
(larger) values, Python usually won't.  So:

a = 12345
b = 12345
a is b  # probably not true
a = 0
b = 0
a is b  # always true


A key point is that you never really "assign a value to a variable".  What
you really do is "bind an object reference to a name".  The long,
simultaneous assignment form binds the same object reference to multiple
variables:

a = b = c = d = 12345
a is b  # always true


But as soon as you reassign any of the variables you will rebind the name
to some other object reference:

a += 1
a is b  # definitely false
a = 12345
a is b  # probably false


Python *could* notice that it already has an integer object with the value
12345, and rebind the name a with a reference to it.  But in practice
Python will probably just create a new integer object with value 12345,
since the Python interpreter doesn't spend large amounts of time looking
through its collection of objects to find ones that can be reused.

Python also has exactly one "None" object, and always uses references to
it whenever you reference None in your code.  This is why it is preferred
Python style to test for None with an "is" test:

a is None


Anyway, the major point I want you to take away from all this: it doesn't
matter whether the "is" test succeeds or fails, if all you care about is
the *value* of a variable.  Python reuses object references to save
memory, because this doesn't affect expressions that only care about the
*value*.  Your logic tests only care about True vs. False; they don't care
about the underlying implementation of how True and False are expressed.


> Another thing I'm trying to do is write a function that tests to see if 
> a list contains exactly one true item, and the rest are false (obviously 
> this would have to be a list of boolean values, I guess). I'm sure this 
> isn't a handy utility, but I enjoy figuring out how to implement it.

This is a simple problem.  I suggest you loop over the list and simply
count how many values are false, and how many are true.  I just wrote and
tested this function in about a minute.

The list doesn't have to be a list of booleans, actually.  Python has a
set of rules for evaluating other values as booleans:

if 0:
    pass  # never executed; 0 always false

if "":
    pass  # never executed; 0-length string always false

if []:
    pass  # never executed; 0-length list always false


So, don't test to see if something is equal to True or False:

if 0 == False:
    pass  # never executed; False and 0 do not directly compare


You *could* do this, but I don't really recommend it:

if bool(0) == False:
    pass  # always executed


Do this:

if not 0:
    pass  # always executed

if 1:
    pass  # always executed


To convert a random value into a boolean value, you could use either
"bool()" or you could use "not not":

a = not not 0
b = bool(0)


"not not" will work on older versions of Python that didn't have an
explicit boolean type; "not 0" would return 1 in that case.  "bool()"
will work in Python 2.2 and newer.
-- 
Steve R. Hastings    "Vita est"
steve at hastings.org    http://www.blarg.net/~steveha




More information about the Python-list mailing list