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
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
Cheers,
Ben
> 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.
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.
> 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:
> 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>
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
Thanks a ton!
Ben