Skip to content

functools.partial placeholders #119127

Description

@dg-pb

Feature or enhancement

Proposal:

I know that this has been brought up in the past, but I would appreciate if this was reconsidered. I would be happy to bring this up to a nice level.

fromfunctoolsimportpartialfrompartial2importpartialaspartial2, Placeholder_=VOID=Placeholder()
%timeitpartial(opr.sub, 1, 2) # 130 ns%timeitpartial2(opr.sub, 1, 2) # 155 nsp1=partial(opr.sub, 1)
p2=partial2(opr.sub, 1)
p3=partial2(opr.sub, _, 1)
p4=partial2(opr.sub, VOID, 1)
print(p1(2)) # -1print(p2(2)) # -1print(p3(2)) # 1print(p4(2)) # 1%timeitp1(2) # 48 ns%timeitp2(2) # 52 ns%timeitp3(2) # 54 ns%timeitp4(2) # 54 ns

The logic is as follows:

defpartial(func, *p_args, **p_kwds):
p_args=list(p_args)
nvoid=sum(aisVOIDforainp_args)
arng=range(len(p_args))
defwrapper(*args, **kwds):
iflen(args) <nvoid:
raiseValueError('Not all VOIDs are filled')
t_args=p_args.copy()
j=0foriinarng:
ifp_args[i] isVOID:
t_args[i] =args[j]
j+=1t_args.extend(args[j:])
returnfunc(*t_args, **{**p_kwds, **kwds})
returnwrapper

vectorcall change looks like:

if (np) {
nargs_new=pto_nargs+nargs-np;
Py_ssize_tip=0;
for (Py_ssize_ti=0; i<pto_nargs; i++) {
if (PyObject_TypeCheck(pto_args[i], &placeholderType)){
memcpy(stack+i, args+ip, 1*sizeof(PyObject*));
ip+=1;
} else {
memcpy(stack+i, pto_args+i, 1*sizeof(PyObject*));
}
}
if (nargs_total>np){
memcpy(stack+pto_nargs, args+np, (nargs_total-np) *sizeof(PyObject*));
}
// EO Placeholders ------
} else {

Has this already been discussed elsewhere?

I have already discussed this feature proposal on Discourse

Links to previous discussion of this feature:

https://discuss.python.org/t/functools-partial-placeholder-arguments/53487

Linked PRs

Metadata

Metadata

Assignees

Labels

extension-modulesC modules in the Modules dirtype-featureA feature request or enhancement

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions