simultaneous assignment

J

John Salerno

Is there a way to assign multiple variables to the same value, but so
that an identity test still evaluates to False?

e.g.:
True # not sure if this is harmful

The first line above is the only way I know to do it, but it seems to
necessarily lead to the true identity test.
 
D

Diez B. Roggisch

John said:
Is there a way to assign multiple variables to the same value, but so
that an identity test still evaluates to False?

e.g.:

True # not sure if this is harmful

The first line above is the only way I know to do it, but it seems to
necessarily lead to the true identity test.

Yes, and there is no way around that - given that python has not an
overloadable assignment operator as e.g. C++ offers (praise the BDFL!). The
semantics of what looks like assignment in python is "I've got a fancy
object somewhere, and now I want to be able to refer to it by that nice
name here". Actually things are somewhat more complicated in case of
list/dictionary element assignment, but for your case that is irrelevant.

Besides, depending on what you assign (e.g. integers, as well as the boolean
constants I guess) you might not even have the choice to guarantee how the
identity test results anyway. Consider this:

I can't imagine what you're actually after here, but assuming that you
really need this and that we're talking "real" objects here, sequence
unpacking and assignment might come handy here, together with a small
list-comp:

a, b, c = [copy.copy(o) for i in xrange(3)]


Diez
 
B

Boris Borcic

John said:
Is there a way to assign multiple variables to the same value, but so
that an identity test still evaluates to False?

e.g.:

True # not sure if this is harmful

The first line above is the only way I know to do it, but it seems to
necessarily lead to the true identity test.
def __eq__(*blah) : return False

 
J

John Salerno

Diez said:
I can't imagine what you're actually after here, but assuming that you
really need this

Hard to explain because I'm still trying to figure out how to do it
myself. I'm trying to solve a little puzzle using Python, even though
I'm sure it's not necessary. 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.

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.
 
D

Diez B. Roggisch

John said:
Hard to explain because I'm still trying to figure out how to do it
myself. I'm trying to solve a little puzzle using Python, even though
I'm sure it's not necessary. 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.

Then use a Proposition-class that holds the actual value.
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).

No - you can for example override the comparison-semantics on the
Proposition-class to be comparable with True/False with the proper
semantics:




class Proposition(object):

def __init__(self, v):
self._v = v


def __eq__(self, o):
return self._v == o


TrueProposition = Proposition(True)
FalseProposition = Proposition(False)

print True == TrueProposition
print False == TrueProposition
print False == FalseProposition



Diez
 
J

John Salerno

Diez said:
Then use a Proposition-class that holds the actual value.


No - you can for example override the comparison-semantics on the
Proposition-class to be comparable with True/False with the proper
semantics:

Hmm, classes still scare me a little, but I should consider this. The
only thing is, it is not known in advance if the propositions are true
or false, you have to figure that out yourself based on the combination
of the statements given. I don't know if this changes the idea behind
your Proposition class...I'll have to give it some more thought.
 
D

David Isaac

John Salerno said:
Is there a way to assign multiple variables to the same value, but so
that an identity test still evaluates to False?

Make sure the value is not a singleton.
Assign them one at a time.True

Hope that helps,
Alan Isaac
 
D

Diez B. Roggisch

Hmm, classes still scare me a little, but I should consider this. The
only thing is, it is not known in advance if the propositions are true
or false, you have to figure that out yourself based on the combination
of the statements given. I don't know if this changes the idea behind
your Proposition class...I'll have to give it some more thought.

No, that was just an example to illustrate the comparison semantics. I don't
know enough about your problem to model it more appropriately.

Besides, you can of course change that self._v of a proposition.

Diez
 
B

bruno at modulix

John said:
Is there a way to assign multiple variables to the same value,
but so
that an identity test still evaluates to False?

re-phrase it according to how Python works, and you'll get the answer:

"Is there a way to bind multiple names to the same object, but so the
identity of this object is different from the identity of this object ?"

the statement:
a = False
doesn't mean "assign the value False to the variable a", but "make the
name 'a' reference the object False" - which is quite different.
True # not sure if this is harmful

Using identity test for boolean tests is usually not a good idea since
many other objects evals to True or False in a boolean context while not
being neither the True nor the False objects.
The first line above is the only way I know to do it, but it seems to
necessarily lead to the true identity test.

It does.

Now if I may ask: what is your actual problem ?
 
J

John Salerno

bruno said:
Now if I may ask: what is your actual problem ?

Ok, since you're so curious. :)

Here's a scan of the page from the puzzle book:
http://johnjsalerno.com/spies.png

Basically I'm reading this book to give me little things to try out in
Python. There's no guarantee that this puzzle is even conducive to (or
worthy of) a programming solution.
 
S

Steve R. Hastings

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.
 
J

John Salerno

Steve said:
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.

Great explanation. Thanks!
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.

Yeah, after trying some crazy things, I just wrote it this way:

def truth_test(seq):
truth = 0
for item in seq:
if item:
truth += 1
if truth == 1:
return True
else:
return False

Not sure I like having to keep a counter though, but the other stuff I
did was really convoluted, like checking to see if the first item was
True, and if it was, popping it from the list and iterating over the
rest of the items (needless to say, the in-place change wasn't helpful).
 
G

Grant Edwards

Yeah, after trying some crazy things, I just wrote it this way:

def truth_test(seq):
truth = 0
for item in seq:
if item:
truth += 1
if truth == 1:
return True
else:
return False

Not sure I like having to keep a counter though, but the other stuff I
did was really convoluted, like checking to see if the first item was
True, and if it was, popping it from the list and iterating over the
rest of the items (needless to say, the in-place change wasn't helpful).

Python knows how to count. :)

def countFalse(seq):
return len([v for v in seq if not v])

def countTrue(seq):
return len([v for v in seq if v])

def truth_test(seq):
return countTrue(seq) == 1
 
J

John Salerno

Grant said:
Python knows how to count. :)

def countFalse(seq):
return len([v for v in seq if not v])

def countTrue(seq):
return len([v for v in seq if v])

def truth_test(seq):
return countTrue(seq) == 1

Gosh, so much to learn! Of course, I already know all about list
comprehensions, but now I just need to learn to *use* them! :)
 
D

Dave Hansen

On Tue, 02 May 2006 18:52:48 GMT in comp.lang.python, John Salerno

[...]
Yeah, after trying some crazy things, I just wrote it this way:

def truth_test(seq):
truth = 0
for item in seq:
if item:
truth += 1
if truth == 1:
return True
else:
return False

You could replace those last four lines with

return truth == 1
Not sure I like having to keep a counter though, but the other stuff I

Well, if you want something minimalist, you could try

def truth_test(seq):
return sum(1 for item in seq if item) == 1

Though I'm not sure it's really any clearer...
did was really convoluted, like checking to see if the first item was
True, and if it was, popping it from the list and iterating over the
rest of the items (needless to say, the in-place change wasn't helpful).

Perhaps something like

def truth_test(seq):
found = False
for item in seq:
if item:
if found:
return False
found = True
return found

Gets you an early exit, anyway...

All code untested. Regards,
-=Dave
 
B

Boris Borcic

Steve said:
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

of course they do - ie isinstance(False,int) is True and False == 0
 
G

Grant Edwards

Python knows how to count. :)

def countFalse(seq):
return len([v for v in seq if not v])

def countTrue(seq):
return len([v for v in seq if v])

def truth_test(seq):
return countTrue(seq) == 1

Gosh, so much to learn! Of course, I already know all about list
comprehensions, but now I just need to learn to *use* them! :)

That's the part that takes a while...
 
B

Boris Borcic

Grant said:
Python knows how to count. :)

def countFalse(seq):
return len([v for v in seq if not v])

def countTrue(seq):
return len([v for v in seq if v])

def truth_test(seq):
return countTrue(seq) == 1

I'd suggest the more direct

def countFalse(seq) :
return sum(1 for v in seq if not v)

def countTrue(seq) :
return sum(1 for v in seq if v)

- not to speak of

def countFalse(seq) :
return sum(not v for v in seq)

def countTrue(seq) :
return sum(bool(v) for v in seq)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,780
Messages
2,569,611
Members
45,280
Latest member
BGBBrock56

Latest Threads

Top