implementing functools.partial that prepends addit

2019-04-06 13:22发布

问题:

The documentation for functools.partial says that it is "roughly equivalent to":

def partial(func, *args, **keywords):
    def newfunc(*fargs, **fkeywords):
        newkeywords = keywords.copy()
        newkeywords.update(fkeywords)
        return func(*(args + fargs), **newkeywords)  # line to change
    newfunc.func = func
    newfunc.args = args
    newfunc.keywords = keywords
    return newfunc

If I wanted to implement a version that prepends the additional arguments, it seems like I'd just have to change the indicated line.

Are there any other features/gotchas that I should be worried about in just copying this code?

回答1:

Looking at the source code for _functoolsmodule.c, I don't think there's much to worry about.

The module implementation of partial handles pickling and repr, but everything else looks like it works as in the documentation so presumably the reason it is implemented in C is just for efficiency. There is also the fact that it is a type rather than just being a function closure.

Note, however, that in the documentation example, func, args and keywords are purely cosmetic; they are not overridable as they are with actual functools.partial instances. One alternative would be to subclass functools.partial:

class rpartial(partial):
    def __call__(self, *args, **kwargs):
        kw = self.keywords.copy()
        kw.update(kwargs)
        return self.func(*(args + self.args), **kwargs)


回答2:

One pitfall is how your partial assignment would handle arbitrary arguments, such as in the following example:

def f(a,b, *args):
    pass

Now partially apply f to the arguments 1 and 2:

g = partial(f, 1, 2)

What is the value of the parameter b in g? Is it 1, or is it still awaiting a value? For that matter, what is the value of a? Put another way, how many, if any, of the supplied arguments should be treated as additional arguments.