simultaneous assignment

S

Steve R. Hastings

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! :)

Play around with them. They are fun. :)


We could also use "generator expressions", available only in
Python 2.4 and newer.

A list comprehension always builds a list. A generator expression can
return values one at a time.

[v for v in seq if v] # builds a list and returns it
(v for v in seq if v) # returns a generator object

len([v for v in seq if v]) # builds a list, then feeds it to len()
len(v for v in seq if v) # gen obj feeds values to len one at a time


The generator expression saves Python from having to build a list and then
destroy the list. It's useful when you only care about the *values* and
you don't want to save the list.

For a short list, the savings are small; but for a really large list, a
generator expression can save a lot of wasted effort in building the new
list and destroying it.


Python 2.5 will be introducing two new functions, "all()" and "any()",
which are intended for use mostly with generator expressions:

any(v for v in seq if v) # true if any v evaluates true
all(v for v in seq if v) # true if *all* v evalute true


Or a better example:

any(is_green(x) for x in lst) # true if any value in list is green
 
B

Boris Borcic

Steve said:
len([v for v in seq if v]) # builds a list, then feeds it to len()
len(v for v in seq if v) # gen obj feeds values to len one at a time

note that generators have no defined length - precisely because they feed values
one at a time while you need them all together to speak of a length. The second
expression will raise a TypeError because of that. If you want to count objects
with a generator expression, use

sum(1 for v in seq if some_condition(v))

which is also clearer imho; summing ones for each item satisfying a condition -
isn't that a definition of counting ?
 
J

John Salerno

Steve said:
We could also use "generator expressions", available only in
Python 2.4 and newer.

A list comprehension always builds a list. A generator expression can
return values one at a time.

[v for v in seq if v] # builds a list and returns it
(v for v in seq if v) # returns a generator object

Woah, interesting. Somehow I don't think I knew that generators could
exist outside of generator functions (using yield)! I was wondering why
the second one above worked without brackets. :)
 
G

Grant Edwards

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)

I guess I don't see how that is more direct.

If you want to know how many items are in a seqneuce, you call
len().

That's what it's for.

The number of objects in a list is returned in O(1) time by
len(sequence).

Converting that list to a list of 1's and then summing the 1's
is O(N).
 
T

Terry Reedy

John Salerno said:
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.

X+Y+Z == 1 # or bool(X)... if not booleam
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.

Use sum(). Being able to count true values by adding is a reason bool is a
subclass of int.

Terry Jan Reedy
 
R

Roger Miller

Steve said:
a = 0
b = 0
a is b # always true

Is this guaranteed by the Python specification, or is it an artifact of
the current implementation? My understanding has been that an
implementation is free to share integer objects or not, so using 'is'
as an equality test takes you into undefined territory, regardless of
the size of the value.
 
B

Boris Borcic

Grant said:
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)

I guess I don't see how that is more direct.

If you want to know how many items are in a seqneuce, you call
len().

sum doesn't construct a sequence
That's what it's for.

The number of objects in a list is returned in O(1) time by
len(sequence).

yeah, but you need to construst the list first, and that isn't O(1) neither in
time or space.
Converting that list to a list of 1's

that's not what my suggestion is doing

and then summing the 1's
 
B

Boris Borcic

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

def spyAreports(W,X,Y,Z) :
return W+X+Y == X+Y+Z == W+Z == 1*True

def spyBreports(W,X,Y,Z) :
return W+X+Y == X+Y+Z == W+Y+Z == 1*True

ft = (False,True)

possibilities = [(W,X,Y,Z) for W in ft for X in ft for Y in ft for Z in ft]

def testReport(report,name) :
print name+"'s report",
n=sum(report(*possibility) for possibility in possibilities)
if n>0 :
if n == len(possibilities) :
print "must",
else :
print "may",
else :
print "can not",
print "be true"

testReport(spyAreports,"Spy A")
testReport(spyBreports,"Spy B")
 
S

Serge Orlov

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

So what you're trying to do is to run over all possible combinations?
Anyway you don't need to worry about identity, since boolean values are
immutable. In general when you see statement like

some_var = immutable value

you can be *sure* you're changing *only* some_var

Warning! Half-spoiler below :) Following is a function run_over_space
from my personal utils package for generating all combinations and an
example how it can be applied to your puzzle:

def decrement(point, space):
""" Yield next point of iteration space """
for coord in range(len(point)):
if point[coord] > 0:
point[coord] -= 1
return
else:
point[coord] = space[coord]
continue
raise StopIteration

def run_over_space(space):
""" Yield all points of iteration space.
Space is a list of maximum values of each dimension"""
point = space[:]
while True:
yield point
decrement(point,space)

def describe_point(spy,w,x,y,z):
if spy:
print "Spy1 is right, ",
else:
print "Spy1 is wrong, ",
print "w, x, y, z = ", w, x, y, z

for point in run_over_space([1,1,1,1,1]):
describe_point(*point)
 
E

Edward Elliott

bruno said:
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 ?"

Which raises an interesting parallel question: is there a way to clone an
arbitrary object? If so you could do this:
False

For lists, a slice-copy creates a clone:
a = [1,2,3]
b = a[:]
id(a) == id(b)
False


For arithmetic types, an identity operation works for large values:
False

but not small ones:
True

With booleans (and None) it will never work since the interpreter only
stores one copy of each value.

I'm not saying this approach is a good idea -- value semantics are almost
always preferable, and playing with interpreter internals usually leads to
trouble. But as an academic exercise, how close can you get to a universal
clone function?
 
G

Gary Duzan

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.

Exhaustive search is quite practical for this problem:

[(x,y,z,w) for x in (True, False)
for y in (True, False)
for z in (True, False)
for w in (True, False)
if spy(x,y,x,w)]

Given the appropriate spy() function, this will return a set of
values for the truthful (logically coherent) spy and nothing for
the other spy. The details are left as an exercise for the reader.
:)

Gary Duzan
Motorola CHS
 
H

Heiko Wundram

Am Dienstag 02 Mai 2006 22:39 schrieb Edward Elliott:
Which raises an interesting parallel question: is there a way to clone an
arbitrary object?

Yes, check the copy module.

copy.copy() does a shallow copy of the parameter, copy.deepcopy() a deep copy
of the parameter. For the difference between the two, check the manual.
(basically, a deep copy copies the whole object tree for container objects
such as lists/tuples/dicts/instances, a shallow copy copies only the topmost
container)

What sense is there cloning integers/strings? Integer and string objects are
immutable in Python, so why'd you want to have different IDs for an object of
the same value? It's the value you're working with in a program, not the
objects ID. At least it should be, if you're truly intent on working with the
(pseudo-random) object-ID, something with your design is really, really
broken.

--- Heiko.
 
E

Edward Elliott

Heiko said:
Integer and string objects
are immutable in Python, so why'd you want to have different IDs for an
object of the same value? It's the value you're working with in a program,
not the objects ID. At least it should be, if you're truly intent on
working with the (pseudo-random) object-ID, something with your design is
really, really broken.

Hence I said, this is an academic exercise.
 
G

Grant Edwards

Grant said:
Grant Edwards wrote:
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)

I guess I don't see how that is more direct.

If you want to know how many items are in a seqneuce, you call
len().

sum doesn't construct a sequence

Doh! I missed the fact that you used a generator rather than a
list comprehension.
that's not what my suggestion is doing

I see that now.
 
H

Heiko Wundram

Am Dienstag 02 Mai 2006 22:47 schrieb Gary Duzan:
Given the appropriate spy() function, this will return a set of
values for the truthful (logically coherent) spy and nothing for
the other spy. The details are left as an exercise for the reader.

Hummm... Isn't it easier and faster to solve this problem by hand than to code
a Python program for it? I had proofs for what has to be on both papers in
about 30 seconds... ;-)

If you're looking for things to code in Python, I'd rather suggest you look at
number theory than at logic problems. Basically, every logic problem can be
solved by exhaustive search (which is always the same algorithm), whereas a
number theory problem requires that you implement a certain algorithm from
scratch for each problem you're trying to tackle.

Implementing the sieve of Erathosthenes comes to mind straight away.

--- Heiko.
 
B

Bruno Desthuilliers

John Salerno a écrit :
Ok, since you're so curious. :)

Sorry !-)
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.

Well, this is probably a good exercice in boolean logic - which is
something very important in CS.

But my question (sorry, it may not have been clear) was more along the
line of : "why do you worry about identity in the given snippet ?".
Rebinding a name already bound to a given object doesn't affect other
names bound to the same object. So in this case, multiple assignement is
perfectly safe.
 
J

John Salerno

Heiko said:
Hummm... Isn't it easier and faster to solve this problem by hand than to code
a Python program for it? I had proofs for what has to be on both papers in
about 30 seconds... ;-)

Yeah, I had actually already figured it out in my head fairly quickly.
If you're looking for things to code in Python, I'd rather suggest you look at
number theory than at logic problems. Basically, every logic problem can be
solved by exhaustive search (which is always the same algorithm), whereas a
number theory problem requires that you implement a certain algorithm from
scratch for each problem you're trying to tackle.

Thanks for the suggestion. Do you know where I might find number theory
problems that aren't too complicated? (No math degree here, in fact,
just the opposite: English!) :)
 
J

John Salerno

Bruno said:
But my question (sorry, it may not have been clear) was more along the
line of : "why do you worry about identity in the given snippet ?".

Actually, I kind of thought that maybe it *didn't* matter in this
particular example anyway, so my question was meant to be more general
than I might have written it. It seems like the identity issue can be a
problem in certain cases, although I can't think of a case right now! :)
 
G

Grant Edwards

Actually, I kind of thought that maybe it *didn't* matter in
this particular example anyway, so my question was meant to be
more general than I might have written it. It seems like the
identity issue can be a problem in certain cases, although I
can't think of a case right now! :)

When it seems like the "identity issue" is a problem, that
usually indicates you're looking at the problem from the wrong
angle.

1/2 :)
 
B

Bruno Desthuilliers

Heiko Wundram a écrit :
(snip)
If you're looking for things to code in Python, I'd rather suggest you look at
number theory than at logic problems.
>
Basically, every logic problem can be
solved by exhaustive search (which is always the same algorithm), whereas a
number theory problem requires that you implement a certain algorithm from
scratch for each problem you're trying to tackle.

Well... I do see the point, but still boolean logic is a mandatory part
of programming, and one that wannabee programmers should get right.
 

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

Forum statistics

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

Latest Threads

Top