Skip to content

gh-149083: Convert _initial_missing for pure py reduce to sentinel#149536

Open
sobolevn wants to merge 1 commit intopython:mainfrom
sobolevn:issue-149083-functools
Open

gh-149083: Convert _initial_missing for pure py reduce to sentinel#149536
sobolevn wants to merge 1 commit intopython:mainfrom
sobolevn:issue-149083-functools

Conversation

@sobolevn
Copy link
Copy Markdown
Member

@sobolevn sobolevn commented May 8, 2026

This is not covered in #149084

Difference is not big, but noticable. Before:
Снимок экрана 2026-05-08 в 08 09 31

Notice the default parameter repr, which is rather unpretty.

After:
Снимок экрана 2026-05-08 в 08 10 17

skip news, because there should be no user facing changes.

Copy link
Copy Markdown
Member

@JelleZijlstra JelleZijlstra left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe ask Hugo how he feels about applying a few more of these in 3.15? It seems fairly low risk when replacing bare object().

@sobolevn
Copy link
Copy Markdown
Member Author

sobolevn commented May 8, 2026

I agree. It feels like the change should happen together with the addition of sentinel 👍
cc @hugovk

@skirpichev
Copy link
Copy Markdown
Member

It would be nice to fix the C version (it has broken signature now), but it seems that that's not backed yet by the AC. Or did I miss something?

@sobolevn
Copy link
Copy Markdown
Member Author

sobolevn commented May 8, 2026

Yes, AFAIK sentinel is not yet supported by the AC :(

@skirpichev
Copy link
Copy Markdown
Member

Yes, AFAIK sentinel is not yet supported by the AC :(

Attached patch "works for me":

>>> import inspect, functools
>>> inspect.signature(functools.reduce)
<Signature (function, iterable, /, initial=_initial_missing)>
Details

(Don't forgot to run AC.)

diff --git a/Lib/inspect.py b/Lib/inspect.py
index a96b3dc954e..dc5a6e3be88 100644
--- a/Lib/inspect.py
+++ b/Lib/inspect.py
@@ -2200,7 +2200,8 @@ def wrap_value(s):
             except NameError:
                 raise ValueError
 
-        if isinstance(value, (str, int, float, bytes, bool, type(None))):
+        if isinstance(value, (str, int, float, bytes, bool, type(None),
+                              sentinel)):
             return ast.Constant(value)
         raise ValueError
 
diff --git a/Modules/_functoolsmodule.c b/Modules/_functoolsmodule.c
index 19bdf3d47c2..13da7944b61 100644
--- a/Modules/_functoolsmodule.c
+++ b/Modules/_functoolsmodule.c
@@ -9,6 +9,7 @@
 #include "pycore_tuple.h"         // _PyTuple_ITEMS()
 #include "pycore_weakref.h"       // FT_CLEAR_WEAKREFS()
 
+PyObject *_initial_missing;
 
 #include "clinic/_functoolsmodule.c.h"
 /*[clinic input]
@@ -1066,7 +1067,7 @@ _functools.reduce
     function as func: object
     iterable as seq: object
     /
-    initial as result: object = NULL
+    initial as result: object(c_default="NULL") = _functools._initial_missing
 
 Apply a function of two arguments cumulatively to the items of an iterable, from left to right.
 
@@ -1081,7 +1082,7 @@ calculates ((((1 + 2) + 3) + 4) + 5).
 static PyObject *
 _functools_reduce_impl(PyObject *module, PyObject *func, PyObject *seq,
                        PyObject *result)
-/*[clinic end generated code: output=30d898fe1267c79d input=4ccfb74548ce5170]*/
+/*[clinic end generated code: output=30d898fe1267c79d input=7e5eaeb4f8a7a78d]*/
 {
     PyObject *args, *it;
 
@@ -1982,6 +1983,14 @@ _functools_exec(PyObject *module)
     // lru_list_elem is used only in _lru_cache_wrapper.
     // So we don't expose it in module namespace.
 
+    _initial_missing = PySentinel_New("_initial_missing", "_functools");
+    if (_initial_missing == NULL) {
+        return -1;
+    }
+    if (PyModule_Add(module, "_initial_missing", _initial_missing) < 0) {
+        Py_DECREF(_initial_missing);
+        return -1;
+    }
     return 0;
 }
 

Comment thread Lib/functools.py

def reduce(function, sequence, initial=_initial_missing):
"""
reduce(function, iterable, /[, initial]) -> value
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This signature line now looks redundant.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I change the signature in another PR :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants