Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Assignment in a while?

727 views
Skip to first unread message

none

unread,
Apr 2, 2006, 2:47:16 PM4/2/06
to
Hi all,

First, let me preface this by the fact that I'm completely new to the
language, but not to programming in general.

I'm trying to get my feet wet with something near and dear to my heart:
database programming. Here's what I've got:

import pgdb;

dbh = pgdb.connect(database = 'test')
sth = dbh.cursor()
sth.execute("SELECT * FROM capitals")
#while 1:
#results = sth.fetchone()
#if results == None:
#break
#print results
while results = sth.fetchone():
print results

If I try to run the above code, I get a SyntaxError indicating that I
can't do an assignment in the while loop. I found a way around this
(see the commented out while loop), but it seems hackish. Assignment
within a while loop seems like a pretty standard thing, so I'm just
curious what I'm missing.

Thanks in advance,
Ben

Paul Boddie

unread,
Apr 2, 2006, 3:02:24 PM4/2/06
to
none/Ben wrote:
>
> Assignment within a while loop seems like a pretty standard thing, so I'm just
> curious what I'm missing.

The FAQ on this subject? ;-)

http://www.python.org/doc/faq/general/#why-can-t-i-use-an-assignment-in-an-expression

It's "standard" in C-flavoured languages, certainly, but probably not
ubiquitous.

Paul

none

unread,
Apr 2, 2006, 3:14:33 PM4/2/06
to
So it seems that I stumbled on the idiomatic way of doing this then.
Well, as they say, "When in Rome..." :). Thanks for pointing out the
FAQ. I'll be reading up on it.

Cheers,
Ben

bill pursell

unread,
Apr 2, 2006, 3:15:36 PM4/2/06
to
none wrote:

> import pgdb;
>
> dbh = pgdb.connect(database = 'test')
> sth = dbh.cursor()
> sth.execute("SELECT * FROM capitals")
> #while 1:
> #results = sth.fetchone()
> #if results == None:
> #break
> #print results
> while results = sth.fetchone():
> print results
>
> If I try to run the above code, I get a SyntaxError indicating that I
> can't do an assignment in the while loop. I found a way around this
> (see the commented out while loop), but it seems hackish. Assignment
> within a while loop seems like a pretty standard thing, so I'm just
> curious what I'm missing.

A more pythonic way to do that is something like:

for results in sth.fetchall():
print results

(I'm not familiar with pgdb, but if it's a reasonable module it will
have some function that returns an iterator.)

In the beginning of my python experience, I was a bit irritated at
being unable to assign and check a condition in one statement, but the
irritation really doesn't last very long. Python has a huge amount of
inherent beauty, and is well worth the time.

Ant

unread,
Apr 2, 2006, 3:17:20 PM4/2/06
to
There are various ways you could do this:

If the number of results won't be too big:

...
for result in sth.fetchall():
print result

If it may be very large:
...

result = sth.fetchone()
while result:
print result
result = sth.fetchone()

Or perhaps nicer:

...
def result_iterator(result_set):
yield result_set.fetchone()

for result in result_iterator(sth):
print result

HTH.

Duncan Booth

unread,
Apr 2, 2006, 3:20:35 PM4/2/06
to
none wrote:

> If I try to run the above code, I get a SyntaxError indicating that I
> can't do an assignment in the while loop. I found a way around this
> (see the commented out while loop), but it seems hackish. Assignment
> within a while loop seems like a pretty standard thing, so I'm just
> curious what I'm missing.
>

Not much, you cannot assign to a variable in the controlling expression
of a while loop. However, for loops do assign values to variables, so if
the form with the break offends you, try restructuring your code as a for
loop. For example:

for results in iter(sth.fetchone, None):
print results

or in many cases you can just fetch everything in one go:

Fredrik Lundh

unread,
Apr 2, 2006, 3:24:03 PM4/2/06
to pytho...@python.org
"none <"@bag.python.org> wrote:

> So it seems that I stumbled on the idiomatic way of doing this then.
> Well, as they say, "When in Rome..." :). Thanks for pointing out the
> FAQ. I'll be reading up on it.

the idiomatic way to loop in Python is to use iterators/generators. if
you have a callable that fetches data from some resource and returns
a "sentinel" when you get to the end, you can use the iter function to
turn it into an iterator:

>>> help(iter)
Help on built-in function iter in module __builtin__:

iter(...)
iter(collection) -> iterator
iter(callable, sentinel) -> iterator

Get an iterator from an object. In the first form, the argument must
supply its own iterator, or be a sequence.
In the second form, the callable is called until it returns the sentinel.

given this, your loop can be written:

for result in iter(std.fetchone, None):
print result

</F>

Ant

unread,
Apr 2, 2006, 3:28:26 PM4/2/06
to
Forget the last suggestion - I wasn't concentrating :-)

Alex Martelli

unread,
Apr 2, 2006, 8:20:10 PM4/2/06
to
none <""thulben\"@(none)"> wrote:
...

> can't do an assignment in the while loop. I found a way around this
> (see the commented out while loop), but it seems hackish. Assignment
> within a while loop seems like a pretty standard thing, so I'm just
> curious what I'm missing.

I see you've already received many excellent suggestions, and just
wanted to point out the way in which you CAN "assign-and-test" in those
rare occasions where you really want to (in my experience, that boils
down to: I need Python code whose structure is as close as possible to
some other's language -- either because I need to transliterate into
Python some published "reference implementation" kind of algorithm, or
because I know I'm just doing a _prototype_ in Python, and once that's
accepted some poor folks will have to transliterate it into C or
whatever). Anyway, it boils down to something like...:

class ValueHolder(object):
def __init__(self, value=None):
self.set(value)
def set(self, value):
self.value = value
return value
data = ValueHolder()

and then, say, something like...:

while data.set(zip.zop()):
frobnicate(data.value)

Not as Pythonic as iterators etc, but structurally very close to

while (xx=zip.zop()) {
frobnicate(xx);
}

if that's what you need to stick close to!-)


Alex

Ben Thul

unread,
Apr 2, 2006, 7:48:42 PM4/2/06
to
The inline iterator version fits very well with my sensibilities. The
problem that I have with fetchall is that sometimes you need to deal
with a very large dataset. Calling fetchall() on it will put the whole
thing in memory, which is no good. Better to iterate over it one row at
a time, IMO.

Thanks a ton!
Ben

0 new messages