In need of a binge-and-purge idiom

Tim Peters tim_one at email.msn.com
Sun Mar 23 14:19:53 EST 2003


[Magnus Lie Hetland]
> Maybe not the best name, but it somehow describes what's going on...
> So...
>
> I've noticed that I use the following in several contexts:
>
>   chunk = []
>   for element in iterable:
>       if isSeparator(element) and chunk:
>           doSomething(chunk)
>           chunk = []
>   if chunk:
>       doSomething(chunk)
>       chunk = []

Since chunk is initialized to an empty list, the if clause in the loop can
never evaluate to true, so this is equivalent to

    chunk = []
    for element in iterable:
        isSeparator(element)

All variations of the code later in the msg suffer the same problem.  As a
result, I've got no idea what you intend the code to do.  Does calling
isSeparator(element), or <shudder> the process of iterating over iterable,
mutate chunk as a side effect?  If so, "yuck" comes to mind.

If the code made sense <wink>, something like

def terminated_iterator(iterable, a_seperator):
    for element in iterable:
        yield element
    yield a_separator

would produce the original sequence, then tack a_separator on to the end.

> ...
> However, the extra check at the end (i.e. the duplication) is a bit
> ugly. A solution would be:
>
>   ...
>   for element in iterable + separator:
>       ...
>
> but that isn't possible, of course. (It could be possible with some
> fiddling with itertools etc., I guess.)

WRT the preceding,

    for element in terminated_iterator(iterable, seperator):

gets that effect.  More generally,

def concat(*seqs):
    "Generate all the elements of all the argument iterables."
    for seq in seqs:
        for x in seq:
            yield x

and then, e.g.,

    for element in concat(iterable, [seperator]):

> ...
> An alternative is:
>
>   it = iter(iterable)
>   chunk = []
>   while True:
>       try:
>           try:
>               element = it.next()
>           except StopIteration:
>               element = SomeSeparator()
>               break
>       finally:
>           if isSeparator(element) and chunk:
>               doSomething(chunk)
>               chunk = []
>
> But this stuff is really just as bad (or even quite a bit worse) than
> the version with duplication.

Indeed, stick to sane alternatives.






More information about the Python-list mailing list