Coding style

Terry Reedy tjreedy at udel.edu
Tue Jul 18 22:24:09 EDT 2006


"Patrick Maupin" <pmaupin at gmail.com> wrote in message 
news:1153240327.611631.76600 at h48g2000cwc.googlegroups.com...
>
> Carl Banks wrote:
>>     def process_values(lst):
>>         if not lst:
>>             return
>>         do_expensive_initialization_step()
>>         for item in lst:
>>             do_something_with(item)
>>         do_expensive_finalization_step()
>> What if you called the function like this:
>>
>>     process_values(x.strip() for x in values_lst)

> The perverse wish, expressed in the specific example, that SOME piece
> of code SOMEWHERE should PLEASE throw an exception because some idiot
> passed a generator expression rather than a list into a function, is
> not apt to be well received by an audience which strives for generality
> when it makes sense; and I daresay most members of that audience, if
> confronted with the wished-for exception, would fix the function so
> that it quite happily accepted generator expressions, rather than
> changing a conditional to use len() just so that an equivalent
> exception could happen a bit earlier.

Given that the input is going to be scanned by an iterator, it really makes 
sense to me to accept an iterator as input.  (Unless the function is for 
special-case usage in a predefined, never to be expanded, set of 
circumstances in which such generality is not needed.  In such a case, if 
lst: is no problem.)  I think the following, untested rewrite suffices.

def process_values(lst):
    it = iter(lst)
    try:
        item = it.next()
        do_expensive_initialization_step()
        do_something_with(item) # see note
        for item in it:
            do_something_with(item)
        do_expensive_finalization_step()
    except StopIteration:
        pass # or any special empty input code

# note: if writing do_something_with(item) is bothersome,
# replace 3 lines with
        while True:
            do_something_with(item)
            try:
               item = it.next
            except StopIteration:
                break

In general, to work with iterators instead of containers, change

if container:
    do_stuff()
else:
    do_empty()

to

try:
    item = it.next()
    do_modified_stuff() # taking into account that have item already
except StopIteration:
    do_empty()

Guido has so far vetoed adding .__len__() to the iterator protocol because 
a) it is not always possible and b) he want to keep the protocol as simple 
as it is.

Terry Jan Reedy







More information about the Python-list mailing list