Is there a list comprehension for this?

John Machin sjmachin at lexicon.net
Wed Nov 22 15:46:35 EST 2006


Steven D'Aprano wrote:
> On Wed, 22 Nov 2006 02:28:04 -0800, John Machin wrote:
>
> >
> > Steven D'Aprano wrote:
> >> On Tue, 21 Nov 2006 21:00:02 -0800, John Machin wrote:
> >>
> >> > Steven D'Aprano wrote:
> >> >
> >> > [snip]
> >> >
> >> >> def running_sum(dw):
> >> >>     """Return a list of the running sums of sequence dw"""
> >> >>     rs = [0]*len(dw)
> >> >>     for i in range(len(dw)):
> >> >>         rs[i] = dw[i] + rs[i-1]
> >> >
> >> > Please explain to the newbies why there is no exception raised when
> >> > rs[i-1] is executed for i == 0, and state whether you consider this is
> >> > a Good Idea or a Filthy Trick or a Fortunate Accident.
> >>
> >> Because rs[0-1] is just rs[-1], which fetches the LAST item of the list. I
> >> cunningly initialised the list to all zeroes, so adding zero to the first
> >> term doesn't change the result value.
> >>
> >> It is a variation of the sentinel technique, where you add an extra value
> >> to the beginning or end of a list so that you don't need to treat the
> >> first or last item differently. In this specific case, I think it is a
> >> combination of Good Idea and Fortunate Accident, but since the
> >> meaning of list[-1] is both deliberate and well-documented, it is
> >> certainly not a Filthy Trick.
> >>
> >
> > Fair enough. But it does make the concerned reader go back a couple of
> > lines to see why it doesn't run amok.
>
> Nobody said that every piece of code should be instantly comprehensible
> just at a glance.

That's correct. I didn't say it, and nobody else did. You argue ad
extremis, in extremis :-)

My point was merely that it is preferable to be able to understand code
without having to go "OMG!" and then read backwards ...

> Sometimes you do actually have to think about code to
> understand it, even in Python :)

Correct. However I raised the question explicitly in the context of an
answer to a *newbie* ("Please explain to the newbies").
Notwithstandingly, you then mentioned "cunningly" and
"[well-]documented" and now "think" :-)

>
> > Here's my attempt at a
> > no-reader-backtracking solution:
> >
> > def running_sum_2(dw):
> >     rs = dw[:1]
> >     for i in xrange(1, len(dw)):
> >         rs.append(dw[i] + rs[-1])
> >     return rs
> >
> > Comments invited.
>

[snip]

>
> Although the speed difference disappears (or even reverses) for small
> enough lists. Either way, it isn't really a major speed difference --

As you say. Perhaps I should have stated in advance how many goalposts
and whether they had a cross-bar or not :-) I was hoping for comments
on the understandibility or otherwise of rs[-1]. My use of xrange was
out of habit; it wasn't intended to provoke the cannonball run.
>
> But why build a list of all the running sums when you probably only need
> them one at a time? Here's a generator version that can take any iterable,
> not just a sequence:
>

... and whether the cross-bar had a net slung from it :-)

Why? (1) Because that's what the OP was asking for IIRC. (2) Because
some applications (at least back when the storage mechanism was squared
paper) involved cumulative sums of cumulative sums of ... generator
version, please :-)

N.B. This is even more fun than discussing cricket with my Pommie
neighbour; keep it up :-)

Best regards,
John




More information about the Python-list mailing list