
Nick, sorry, but your arguments still make little sense to me. I think you're pushing an analogy between `sum()` details and `accumulate()` waaaaay too far, changing a simple idea into a needlessly complicated one. `accumulate()` can do anything at all it wants to do with a `start` argument (if it grows one), and a "default" of start=0 makes no sense: unlike `sum()`, `accumulate()` is not specifically for use with numeric values and may reject non-numeric types [from the `sum()` docs] `accumulate()` accepts any two-argument function.
itertools.accumulate([1, 2, 3], lambda x, y: str(x) + str(y)) <itertools.accumulate object at 0x0000028AB1B3B448> list(_) [1, '12', '123']
Arguing that it "has to do" something exactly the way `sum()` happens to be implemented just doesn't follow - not even if they happen to give the same name to an optional argument. If the function were named `accumulate_sum()`, and restricted to numeric types, maybe - but it's not. [Nick Coghlan <ncoghlan@gmail.com>]
... That concern mostly goes away if the new parameter is deliberately called something *other than* "start" (e.g. "prepend=value", or "first=value"), but it could also be addressed by offering a dedicated "yield_start" toggle, such that the revised semantics were:
def accumulate(iterable, func=operator.add, start=0, yield_start=False): it = iter(iterable) total = start if yield_start: yield total for element in it: total = func(total, element) yield total
That approach would have the advantage of making the default value of "start" much easier to document (since it would just be zero, the same as it is for sum()), and only the length of the input iterable and "yield_start" would affect how many partial sums were produced.
As above, start=0 is senseless for `accumulate` (despite that it makes sense for `sum`). Raymond gave the obvious implementation in his original message. If you reworked your implementation to accommodate that NO sensible default for `start` exists except for the one Raymond used (a unique object private to the implementation, so he knows for sure whether or not `start` was passed), you'd end up with his implementation ;-) `yield_start` looks like a nuisance in any case. As already explained, most uses want the `start` value if it's given, and in cases where it isn't it's trivial to discard by doing `next()` once on the result. Of course it could be added - but why bother?