pythonmemorymemory-management

Why does Python's functools.partial definition use function attributes?


In the functools.partial example definition, function attributes are used in the returned partial function object:

def partial(func, /, *args, **keywords):
    def newfunc(*fargs, **fkeywords):
        newkeywords = {**keywords, **fkeywords}
        return func(*args, *fargs, **newkeywords)
    newfunc.func = func
    newfunc.args = args
    newfunc.keywords = keywords
    return newfunc

What would be the potential problems if those attributes were removed, like below? Shouldn't Python still keep the references to func, args and keywords as long as newfunc is alive?

def partial(func, /, *args, **keywords):
    def newfunc(*fargs, **fkeywords):
        newkeywords = {**keywords, **fkeywords}
        return func(*args, *fargs, **newkeywords)
    return newfunc

I know that the actual implementation of functools.partial may be completely different, but what if it were implemented this way, why are the attributes necessary?


Solution

  • Any implementation needs the function and its canned arguments stored somewhere. In your two examples you use a closure. When these partial implementations return, those values are added to the closure that is returned. In that case, .func, .args and .keywords are redundant. The closure already has them. So, go with option 2.

    But python creates a class for this work instead. .func, .args and .keywords are the only copies of the needed data. The class implementation lets you make a partial of a partial in an efficient manner (it combines the arguments of the two partials) and is a bit tidier when building a string display of the object.

    But your second closure mechanism is fine, just a different way of doing things.