diff --git a/Doc/whatsnew/3.16.rst b/Doc/whatsnew/3.16.rst index 98a8644884a8d7..4ddc836d9b29e4 100644 --- a/Doc/whatsnew/3.16.rst +++ b/Doc/whatsnew/3.16.rst @@ -114,6 +114,12 @@ annotationlib Use :meth:`annotationlib.ForwardRef.evaluate` or :func:`typing.evaluate_forward_ref` instead. +functools +--------- + +* Calling the Python implementation of :func:`functools.reduce` with *function* + or *sequence* as keyword arguments has been deprecated since Python 3.14. + sysconfig --------- diff --git a/Lib/functools.py b/Lib/functools.py index cd374631f16792..73274b94ef37da 100644 --- a/Lib/functools.py +++ b/Lib/functools.py @@ -234,7 +234,7 @@ def __ge__(self, other): _initial_missing = object() -def reduce(function, sequence, initial=_initial_missing): +def reduce(function, sequence, /, initial=_initial_missing): """ reduce(function, iterable, /[, initial]) -> value @@ -264,6 +264,11 @@ def reduce(function, sequence, initial=_initial_missing): return value +try: + from _functools import reduce +except ImportError: + pass + ################################################################################ ### partial() argument application @@ -1178,31 +1183,3 @@ def __get__(self, instance, owner=None): return val __class_getitem__ = classmethod(GenericAlias) - -def _warn_python_reduce_kwargs(py_reduce): - @wraps(py_reduce) - def wrapper(*args, **kwargs): - if 'function' in kwargs or 'sequence' in kwargs: - import os - import warnings - warnings.warn( - 'Calling functools.reduce with keyword arguments ' - '"function" or "sequence" ' - 'is deprecated in Python 3.14 and will be ' - 'forbidden in Python 3.16.', - DeprecationWarning, - skip_file_prefixes=(os.path.dirname(__file__),)) - return py_reduce(*args, **kwargs) - return wrapper - -reduce = _warn_python_reduce_kwargs(reduce) -del _warn_python_reduce_kwargs - -# The import of the C accelerated version of reduce() has been moved -# here due to gh-121676. In Python 3.16, _warn_python_reduce_kwargs() -# should be removed and the import block should be moved back right -# after the definition of reduce(). -try: - from _functools import reduce -except ImportError: - pass diff --git a/Lib/test/test_functools.py b/Lib/test/test_functools.py index a8ee7d119e4bc6..c30386afe41849 100644 --- a/Lib/test/test_functools.py +++ b/Lib/test/test_functools.py @@ -1134,6 +1134,14 @@ def add(x, y): self.assertRaises(TypeError, self.reduce, add, [0, 1], initial="") self.assertEqual(self.reduce(42, "", initial="1"), "1") # func is never called with one item + def test_reduce_with_kwargs(self): + with self.assertRaises(TypeError): + self.reduce(function=lambda x, y: (x or 1) + y, sequence=[1, 2, 3, 4, 5]) + with self.assertRaises(TypeError): + self.reduce(function=lambda x, y: x + y, sequence=[1, 2, 3, 4, 5], initial=1) + with self.assertRaises(TypeError): + self.reduce(lambda x, y: x + y, sequence=[1, 2, 3, 4, 5], initial=1) + @unittest.skipUnless(c_functools, 'requires the C _functools module') class TestReduceC(TestReduce, unittest.TestCase): @@ -1144,12 +1152,6 @@ class TestReduceC(TestReduce, unittest.TestCase): class TestReducePy(TestReduce, unittest.TestCase): reduce = staticmethod(py_functools.reduce) - def test_reduce_with_kwargs(self): - with self.assertWarns(DeprecationWarning): - self.reduce(function=lambda x, y: x + y, sequence=[1, 2, 3, 4, 5], initial=1) - with self.assertWarns(DeprecationWarning): - self.reduce(lambda x, y: x + y, sequence=[1, 2, 3, 4, 5], initial=1) - class TestCmpToKey: diff --git a/Misc/NEWS.d/next/Library/2026-05-08-08-24-01.gh-issue-149537.hVFVnt.rst b/Misc/NEWS.d/next/Library/2026-05-08-08-24-01.gh-issue-149537.hVFVnt.rst new file mode 100644 index 00000000000000..2fb0359a2ea893 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-05-08-08-24-01.gh-issue-149537.hVFVnt.rst @@ -0,0 +1,2 @@ +Remove kw parameters from python version of :func:`functools.reduce` +function.