Since this started, I've been using variants of the following in my own code, wrapping `accumulate`:

    from itertools import accumulate, chain, cycle, islice

    def accum(iterable, func=None, *, initial=None, skipfirst=False):
        if initial is not None:
            iterable = chain([initial], iterable)

        if func is None:
            iterable = accumulate(iterable)
            iterable = accumulate(iterable, func)

        if skipfirst:
            iterable = islice(iterable, 1, None)
        return iterable

I quite like it!  It handles everything that's come up pretty naturally.  A difference from what was discussed before:  I opposed having a `skipfirst` argument because I didn't want an optional argument that _only_ applied if another optional argument was specified.  But `skipfirst` in the above applies regardless of whether `initial` is specified.  It turned out to be useful in cases where the _effect_ of `initial` had been gotten instead via slamming the initial value into the first object returned by `iterable`, and then ignored later by a special first case to throw away the first result `accumulate` returned.

I'm writing this now because it turned out I used it eight times yesterday, which raised it above background noise level ;-)

The first use captures a sequence countless thousands of Python programmers have crafted in various ways by hand:

    def firstfactor(n, limit=1000):
        for p in chain([2, 3],
                       accum(cycle([2, 4]), initial=5)):
            # 2, 3, and integers not divisible by 2 or 3
            # 2, 3, 5, 7, 11, 13, 17, 19, 23, 25, 29, 31, ...
            if p*p > n:
                return n
            if p > limit:
                return 0
            if n % p == 0:
                return p

The same sequence can be gotten more obscurely via:

        for p in chain([2, 3],
            accum(cycle([4, 2]), initial=1, skipfirst=True)):

The remaining 7 uses were in transcribing's Lehman's elegant[1] optimization of Fermat's "difference of squares" factorization method:

    def large(deltas, init):
        for k in accum(cycle(deltas), initial=init):

    # ints divisible by 30
    large([30], 30)

    # ints divisible by 24 but not by 30
    large([24, 24, 24, 48], 24)

    # ints divisible by 12 but not by 30 or 24
    large([24, 48, 24, 24], 12)

    # ints divisible by 18 but not by 30, 24, or 12
    large([36, 72, 36, 36], 18)

    # ints divisible by 6 but not by 30, 24, 12, or 18
    large([36, 24, 12, 24, 12, 24, 36, 12], 6)

    # ints divisible by 2 but not by 30, 24, 12, 18, or 6
    large([2, 4], 2)

    # ints not divisible by 30, 24, 12, 18, 6, or 2
    large([2], 1)

Lehman built his sequence generator "by hand" in Algol. where the delta array (`c` in his code) is inherited from `large`'s enclosing scope, and `large()` is passed just the number of deltas and the initial value.  A more literal transcription of his code would have used:

    def large(deltas, init):
        for k in accum(cycle(deltas), initial=init, skipfirst=True):

instead with the delta lists rotated and with a different initial value.  For example, instead of

    large([24, 24, 24, 48], 24)

above his code uses

    large([48, 24, 24, 24], -24)

The latter needs to ignore the initial (-24) value (except to add it to the first delta: -24 + 48 = 24).  That was more natural in context, due to the way he advanced the generated in a `while True:` loop built out of gotos ;-)


Historical gloss:  Lehman surprisingly transformed Fermat's O(n) method into an O(cube_root(n)) method.  I believe that was the first deterministic factoring method known beating trial division's O(sqrt(n)) time.  Alas for Lehman, Pollard very soon after published his `rho` method, which runs in probabilistic O(sqrt(p)) time where p is n's smallest prime factor, so in worst-case probabilistic O(fourth_root(n)) time.  That relegated Lehman's method to an academic curiosity, although it remains supremely effective if N is the product of two odd primes whose ratio is close to a fraction with "small" numerator and denominator.