while row = c.fetchone(): # syntax error???

Alex Martelli alex at magenta.com
Mon Aug 14 06:50:14 EDT 2000


"Richard Brodie" <R.Brodie at rl.ac.uk> wrote in message
news:8n8btt$1dmu at newton.cc.rl.ac.uk...
>
> "Alex Martelli" <alex at magenta.com> wrote in message
news:8n0d1t0kao at news2.newsguy.com...
>
> > Right.  Assignment is not an expression in Python.  One benefit is that
> > you avoid such errors as coding "while x=y:" where you meant to code
> > "while x==y:".  But it does mean that certain C idioms aren't Python
idioms.
> >
> > The workaround most often used is to change what one'd like to code as:
> >
> >     while row=c.fetchone():    # nope -- Python doesn't like this!
> >         doit(row)
> >
> > into the equivalent Python idiom:
> >
> >     while 1:
> >         row=c.fetchone()
> >         if not row: break
> >         doit(row)
>
> The real problem is the underlying class has a 'C' like API. Returning

What's C-like about it?  If c.fetchone() returns the next 'row', and None
when there's nothing more to be returned, that's basically the same as
a Python's fileobject fo.readline().

> magic numbers like 0 isn't really Python's style.

What "magic number like 0" are we talking about?  I was assuming that
c.fetchone() would return None to say "I have nothing (more) to return",
which is exactly what Python's fileobject does when asked to readline()
when there are no more lines to be read.  So what does it mean "isn't
really Python's style"?  Aren't Python's fileobjects "Python style"?

> The natural way to do
> it in Python (given a more suitable underlying class) is:
>
> for row in c.fetchrows():
>     doit(row)

You can do that on a fileobject by using readlines() instead of readline(),
but sometimes it's a problem -- a huge file could gobble up your memory.
Whatever this c object is, maybe it could have similar problems.  In which
case, wrapping (like fileinput does for fileobjects) is probably best.

Other cases in which having fetchrows() return a list of all items would
be sub-optimal include those where the data are being produced N
items at a time by some other process/thread/machine.  Here, waiting
until all data is in would be sub-optimal by foregoing possibilities to
overlap the processing of already-produced items with the production
of more items.

Here, the wrapper would have to implement buffering -- asking the
underlying object for "as much items as can be had readily without
too much of a wait", exhausting that buffer before going to the
underlying object to fetch again.  And fetchrows() would have to
return a helper object simulating a sequence by doing just such
interactions with the underlying object.

Can be done, sure, but it's pretty sophisticated stuff.  Why should
every application programmer have to re-implement it...?

Once the buffering is in place in terms of get-next-item-if-any,
translating that into Python's sequence-idiom (__getitem__, with
optionally a check that data IS being asked for sequentially to
avoid incident with client code wrongly using indexing via [],
raising exception at end) is 'Python exoterica' -- not really hard,
but not something you want to ask every beginning Pythoneer
to have to understand just so he can loop elegantly on his own
"enumerations".


> As noted, you can always wrap the class. But it's not really Python's
> fault that it was broken in the first place.

I don't see anything "broken in the first place" with Python's fileobjects,
or anything else whose basic underying paradigm is to return "one
sub-object at a time, None when there is nothing more to return".

Why should every user-object reimplement buffering strategies and
suchlike?  Rather, Python should supply a few pre-built wrappers, IMHO.
Anyway, they're not hard to place in a site-configuration module.  But
a given beginner's site might then lack them.  A couple of utilities to
be distributed by-default would do a world of good in that regard.


Alex






More information about the Python-list mailing list