Search code examples
pythonstatic-methodspython-decoratorsfunctools

Python functools.partial - How to apply it to a class method with the static decorator


I know there must be a way to do this. But I'm getting the error "TypeError: the first argument must be callable".

What could I do differently to make this work?

class FaxMachine(object):
    MODEL_NO = '100'

    @staticmethod
    def load_fax(fax, error=''):
        # send fax here

    fail_fax = functools.partial(load_fax, error='PC LOAD LETTER')

Solution

  • staticmethod objects are not callable. They're descriptors that keep references to original functions in their __func__ attributes.

    So the following works:

    # Note: apply staticmethod again
    fail_fax = staticmethod(partial(load_fax.__func__, error='PC LOAD LETTER'))
    

    You could also define a helper function in the class namespace, to avoid unnecessary attribute lookups:

    def _load_fax(fax, error=''):
        # ...
    
    # _load_fax is an ordinary function
    load_fax = staticmethod(_load_fax)
    fail_fax = staticmethod(partial(_load_fax, error='PC LOAD LETTER'))
    

    Though the correct Python 3.4+ solution is to use the partialmethod, which was designed to work with descriptors:

    fail_fax = partialmethod(load_fax, error='PC LOAD LETTER')