Skip to content

Commit 17efa6e

Browse files
sayandipduttaebonnal
authored andcommitted
pythongh-125916: Allow functools.reduce() 'initial' to be a keyword argument (python#125917)
1 parent 8418d66 commit 17efa6e

File tree

8 files changed

+76
-13
lines changed

8 files changed

+76
-13
lines changed

Doc/library/functools.rst

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -453,7 +453,7 @@ The :mod:`functools` module defines the following functions:
453453
.. versionadded:: 3.4
454454

455455

456-
.. function:: reduce(function, iterable[, initial], /)
456+
.. function:: reduce(function, iterable, /[, initial])
457457

458458
Apply *function* of two arguments cumulatively to the items of *iterable*, from
459459
left to right, so as to reduce the iterable to a single value. For example,
@@ -468,7 +468,7 @@ The :mod:`functools` module defines the following functions:
468468

469469
initial_missing = object()
470470

471-
def reduce(function, iterable, initial=initial_missing, /):
471+
def reduce(function, iterable, /, initial=initial_missing):
472472
it = iter(iterable)
473473
if initial is initial_missing:
474474
value = next(it)
@@ -481,6 +481,9 @@ The :mod:`functools` module defines the following functions:
481481
See :func:`itertools.accumulate` for an iterator that yields all intermediate
482482
values.
483483

484+
.. versionchanged:: next
485+
*initial* is now supported as a keyword argument.
486+
484487
.. decorator:: singledispatch
485488

486489
Transform a function into a :term:`single-dispatch <single

Doc/whatsnew/3.14.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,11 @@ functools
320320
to reserve a place for positional arguments.
321321
(Contributed by Dominykas Grigonis in :gh:`119127`.)
322322

323+
* Allow the *initial* parameter of :func:`functools.reduce` to be passed
324+
as a keyword argument.
325+
(Contributed by Sayandip Dutta in :gh:`125916`.)
326+
327+
323328
getopt
324329
------
325330

Lib/functools.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ def __ge__(self, other):
236236

237237
def reduce(function, sequence, initial=_initial_missing):
238238
"""
239-
reduce(function, iterable[, initial], /) -> value
239+
reduce(function, iterable, /[, initial]) -> value
240240
241241
Apply a function of two arguments cumulatively to the items of an iterable, from left to right.
242242

Lib/test/test_functools.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1005,6 +1005,29 @@ def __getitem__(self, i):
10051005
d = {"one": 1, "two": 2, "three": 3}
10061006
self.assertEqual(self.reduce(add, d), "".join(d.keys()))
10071007

1008+
# test correctness of keyword usage of `initial` in `reduce`
1009+
def test_initial_keyword(self):
1010+
def add(x, y):
1011+
return x + y
1012+
self.assertEqual(
1013+
self.reduce(add, ['a', 'b', 'c'], ''),
1014+
self.reduce(add, ['a', 'b', 'c'], initial=''),
1015+
)
1016+
self.assertEqual(
1017+
self.reduce(add, [['a', 'c'], [], ['d', 'w']], []),
1018+
self.reduce(add, [['a', 'c'], [], ['d', 'w']], initial=[]),
1019+
)
1020+
self.assertEqual(
1021+
self.reduce(lambda x, y: x*y, range(2,8), 1),
1022+
self.reduce(lambda x, y: x*y, range(2,8), initial=1),
1023+
)
1024+
self.assertEqual(
1025+
self.reduce(lambda x, y: x*y, range(2,21), 1),
1026+
self.reduce(lambda x, y: x*y, range(2,21), initial=1),
1027+
)
1028+
self.assertRaises(TypeError, self.reduce, add, [0, 1], initial="")
1029+
self.assertEqual(self.reduce(42, "", initial="1"), "1") # func is never called with one item
1030+
10081031

10091032
@unittest.skipUnless(c_functools, 'requires the C _functools module')
10101033
class TestReduceC(TestReduce, unittest.TestCase):

Misc/ACKS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -485,6 +485,7 @@ Luke Dunstan
485485
Virgil Dupras
486486
Bruno Dupuis
487487
Andy Dustman
488+
Sayandip Dutta
488489
Gary Duzan
489490
Eugene Dvurechenski
490491
Karmen Dykstra
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Allow the *initial* parameter of :func:`functools.reduce` to be passed as a keyword argument.
2+
Patch by Sayandip Dutta.

Modules/_functoolsmodule.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -937,8 +937,8 @@ _functools.reduce
937937
938938
function as func: object
939939
iterable as seq: object
940-
initial as result: object = NULL
941940
/
941+
initial as result: object = NULL
942942
943943
Apply a function of two arguments cumulatively to the items of an iterable, from left to right.
944944
@@ -953,7 +953,7 @@ calculates ((((1 + 2) + 3) + 4) + 5).
953953
static PyObject *
954954
_functools_reduce_impl(PyObject *module, PyObject *func, PyObject *seq,
955955
PyObject *result)
956-
/*[clinic end generated code: output=30d898fe1267c79d input=d233c2670cba7f66]*/
956+
/*[clinic end generated code: output=30d898fe1267c79d input=1511e9a8c38581ac]*/
957957
{
958958
PyObject *args, *it;
959959

Modules/clinic/_functoolsmodule.c.h

Lines changed: 37 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)