Loop-and-a-half (Re: Curious assignment behaviour)

Donn Cave donn at u.washington.edu
Fri Oct 12 20:03:17 EDT 2001


Quoth "Jyrinx" <jyrinx at mindspring dot com>:
| Erm, I'm hardly a seasoned hacker, but if I may toss in a few cents ...
|
| > |     n = compute_number_of_items()
| > |     for i in range(n):
| > |        try: process_an_item(items[i])
| > |        except: break
| > |     update_database('number of items processed = ' % i)
|
| Paul Rubin pointed out the problem with the empty "items" array (i never
| gets initialized, exception is thrown), saying that the C way is more
| concise and deals with this. Donn Cave said he doesn't like the "for x in
| range()" stuff, would opt for a while loop with manual incrementation.
|
| I like Python's for loop, "range()" idiom and all. In any case, I should
| think the above code would be clearer anyway with an explicit check for an
| empty list:
|
|     n = compute_number_of_items()
|     if n == 0:
|         update_database('no items processed')
|    else:
|         for i in range(n):
|            try: process_an_item(items[i])
|            except: break
|         update_database('number of items processed = ' % i) # (Hmm? I
| thought the % operator was supposed to be used with a string and a
| dictionary? Not that # I would know what I'm talking about ... :-)
|
| Or, if you didn't want to make an extra branch and didn't want the
| uninitialized-i problem, why not just initialize it to 0 before the loop?

Good practice for sure, but I think the point may have been that
you shouldn't have to go to so much extra trouble, for safe code.
You pretty much had to anticipate the problem, to think to make
those provisions for it, and if 0 items is an exceptional case,
you'd be very likely to to neglect them.  Once this potential occurs
to you, it's very easy to solve that problem.

Here's an idea - suppose the block has its own scope!  Now a reference
to "i" is illegal outside the block.  More or less like global scope
vs. function local - if i was assigned to prior to the block, then the
binding is inherited by the block, but new names are bound in the block
scope.  Not just the for variable, any assignment - after all, the
problem is exactly the same.  If you don't know whether you're going
to execute the block even once, then you need to provide defaults, as
you did in your example.  That might get a bit tedious, but now we're
talking about helping people use good programming practices (forcing
them to, that is.)

	Donn Cave, donn at u.washington.edu



More information about the Python-list mailing list