Skip to content

Commit 70e47ed

Browse files
committed
small CR changes and doc updates
1 parent a8bd3ae commit 70e47ed

File tree

3 files changed

+21
-17
lines changed

3 files changed

+21
-17
lines changed

Doc/library/functools.rst

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -373,20 +373,24 @@ The :mod:`functools` module defines the following functions:
373373
only one positional argument is provided, while there are two placeholders
374374
in :ref:`partial object <partial-objects>`.
375375

376-
When successively using :func:`partial` existing :data:`!Placeholder`
377-
sentinels are filled first. A place for positional argument is retained
378-
when :data:`!Placeholder` sentinel is replaced with a new one:
376+
Successive :func:`partial` applications fill :data:`!Placeholder` sentinels
377+
of the input :func:`partial` objects with new positional arguments.
378+
A place for positional argument can be retained by inserting new
379+
:data:`!Placeholder` sentinel to the place held by previous :data:`!Placeholder`:
379380

380381
>>> from functools import partial, Placeholder as _
381-
>>> count = partial(print, _, _, _, 4)
382-
>>> count = partial(count, _, _, 3)
383-
>>> count = partial(count, _, 2)
384-
>>> count = partial(count, _, 5) # 5 is appended after 4
385-
>>> count(1)
382+
>>> show5 = partial(print, _, _, _, 4)
383+
>>> show5 = partial(show5, _, _, 3)
384+
>>> show5 = partial(show5, _, 2)
385+
>>> show5 = partial(show5, _, 5) # 5 is appended after 4
386+
>>> show5(1)
386387
1 2 3 4 5
387388

389+
Note, :data:`!Placeholder` has no special treatment when used for keyword
390+
argument of :data:`!Placeholder`.
391+
388392
.. versionchanged:: 3.14
389-
Support for :data:`Placeholder` in *args*
393+
Added support for :data:`Placeholder` in positional arguments.
390394

391395
.. data:: Placeholder
392396

Lib/test/test_functools.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -556,8 +556,8 @@ class TestPartialPySubclass(TestPartialPy):
556556
def test_subclass_optimization(self):
557557
p = py_functools.partial(min, 2)
558558
p2 = self.partial(p, 1)
559-
assert p2.func is min
560-
assert p2(0) == 0
559+
self.assertIs(p2.func, min)
560+
self.assertEqual(p2(0), 0)
561561

562562

563563
class TestPartialMethod(unittest.TestCase):
@@ -702,8 +702,8 @@ class PartialMethodSubclass(functools.partialmethod):
702702
pass
703703
p = functools.partialmethod(min, 2)
704704
p2 = PartialMethodSubclass(p, 1)
705-
assert p2.func is min
706-
assert p2.__get__(0)() == 0
705+
self.assertIs(p2.func, min)
706+
self.assertEqual(p2.__get__(0)(), 0)
707707

708708

709709
class TestUpdateWrapper(unittest.TestCase):

Modules/_functoolsmodule.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -150,14 +150,13 @@ partial_new(PyTypeObject *type, PyObject *args, PyObject *kw)
150150
PyObject *func, *pto_args, *new_args, *pto_kw;
151151
partialobject *pto;
152152
Py_ssize_t pto_phcount = 0;
153-
Py_ssize_t new_nargs = PyTuple_GET_SIZE(args);
153+
Py_ssize_t new_nargs = PyTuple_GET_SIZE(args) - 1;
154154

155-
if (new_nargs < 1) {
155+
if (new_nargs < 0) {
156156
PyErr_SetString(PyExc_TypeError,
157157
"type 'partial' takes at least one argument");
158158
return NULL;
159159
}
160-
new_nargs--;
161160
func = PyTuple_GET_ITEM(args, 0);
162161
if (!PyCallable_Check(func)) {
163162
PyErr_SetString(PyExc_TypeError,
@@ -411,7 +410,7 @@ partial_vectorcall(partialobject *pto, PyObject *const *args,
411410
tot_nargs = pto_nargs + nargs - pto_phcount;
412411
Py_ssize_t j = 0; // New args index
413412
for (Py_ssize_t i = 0; i < pto_nargs; i++) {
414-
if (pto_args[i] == pto->placeholder){
413+
if (pto_args[i] == pto->placeholder) {
415414
stack[i] = args[j];
416415
j += 1;
417416
}
@@ -500,6 +499,7 @@ partial_call(partialobject *pto, PyObject *args, PyObject *kwargs)
500499
if (pto_phcount) {
501500
Py_ssize_t pto_nargs = PyTuple_GET_SIZE(pto->args);
502501
Py_ssize_t tot_nargs = pto_nargs + nargs - pto_phcount;
502+
assert(tot_nargs >= 0);
503503
tot_args = PyTuple_New(tot_nargs);
504504
if (tot_args == NULL) {
505505
Py_XDECREF(tot_kw);

0 commit comments

Comments
 (0)