Remove positional only restriction on `initial` parameter of `reduce`

A lot of code written using functools.reduce is generally hard to understand (if GvR is to be believed!), this is exacerbated by the fact that the initial argument is position-only.

# instead of this
reduce(sub, [1, 1, 2, 3, 5, 8], 21)
# the following version is objectively more clear
reduce(sub, [1, 1, 2, 3, 5, 8], initial=21)

Ideally, it should have been strictly keyword-only argument (just like in itertools.accumulate). But understandably that is not a viable option at this point in time. However, I can’t see any reason to mandate position-only use, nor can I imagine a scenario where having the ability to specify initial via keyword would be detrimental to existing or new code.

In my view, the clarity alone is justification enough, additionally this would be helpful to make a partial function out of reduce with default initial argument.

EDIT: A recent example of such change was in str.replace’s count method, which was position-only before 3.13.

19 Likes

Seems reasonable to me, feel free to open an issue and PR and we can likely make this change in Python 3.14.

5 Likes

Perfect! Will do that! Since this would potentially be my first contribution in cpython, it may take a little more time than necessary.

1 Like

Sounds good. I took a quick look at the code and it might not be trivial to do, since the function doesn’t use Argument Clinic. But it’s definitely doable.

Here’s the PR.

I used PyArg_ParseTupleAndKeywords for parsing the kwd. I admit I am inexperienced in this area, I am willing to try fix any mess I made. Thanks

I took look on the comment about AC and it seems to be slightly misleading. Hardly reusing args instead of just another local variable will affect performance significantly.

Edit: indeed, this even look faster with AC on simple benchmarks.

I’m in favor of making all parameters positional-and-keyword.
Every parameter of the Python implementation of functools.reduce is positional-and-keyword, so making all parameters positional-and-keyword for _functools (C extension) will match Python implementation. More discussion about it: gh-121676: Raise a ``DeprecationWarning`` if the Python implementation of ``functools.reduce`` is called with a keyword args by Eclips4 · Pull Request #121677 · python/cpython · GitHub

5 Likes

Is there a performance benefit in using positional-only parameters? I don’t know enough about the internals to say for sure.

Parsing a signature with only pos-only args is more efficient, if I understand your question correctly.

1 Like

That’s what I asked, thanks!

Not saying that should stop us from changing the signature, was mostly curious.

I saw that comment too and was suspicious, but didn’t run any benchmarks. If benchmarks show it’s faster (or at least, not slower) with AC, we should definitely switch.

1 Like

In the meantime, I just came up with an abusive hack for the readability problem:

reduce(add, tuples, _initial:=())

Regarding the PR, do I need to do anything else? If not, what happens now?

I don’t mean to pester, I am not familiar with the PR life cycle in cpython, so I just wanted to know.

1 Like

See Lifecycle of a pull request

If your pull request has not received any notice from reviewers (that is, no comment made) after one month, first “ping” the issue on the issue tracker to remind the subscribers that the pull request needs a review. If you don’t get a response within a week after pinging the issue, you can post on the Core Development Discourse category to ask for someone to review your pull request.

1 Like