Search code examples
pythondecoratorstatic-methods

Python decorator as a staticmethod


I'm trying to write a python class which uses a decorator function that needs information of the instance state. This is working as intended, but if I explicitly make the decorator a staticmetod, I get the following error:

Traceback (most recent call last):
  File "tford.py", line 1, in <module>
    class TFord(object):
  File "tford.py", line 14, in TFord
    @ensure_black
TypeError: 'staticmethod' object is not callable

Why?

Here is the code:

class TFord(object):
    def __init__(self, color):
        self.color = color

    @staticmethod
    def ensure_black(func):
        def _aux(self, *args, **kwargs):
            if self.color == 'black':
                return func(*args, **kwargs)
            else:
                return None
        return _aux

    @ensure_black
    def get():
        return 'Here is your shiny new T-Ford'

if __name__ == '__main__':
    ford_red = TFord('red')
    ford_black = TFord('black')

    print ford_red.get()
    print ford_black.get()

And if I just remove the line @staticmethod, everything works, but I do not understand why. Shouldn't it need self as a first argument?


Solution

  • This is not how staticmethod is supposed to be used. staticmethod objects are descriptors that return the wrapped object, so they only work when accessed as classname.staticmethodname. Example

    class A(object):
        @staticmethod
        def f():
            pass
    print A.f
    print A.__dict__["f"]
    

    prints

    <function f at 0x8af45dc>
    <staticmethod object at 0x8aa6a94>
    

    Inside the scope of A, you would always get the latter object, which is not callable.

    I'd strongly recommend to move the decorator to the module scope -- it does not seem to belong inside the class. If you want to keep it inside the class, don't make it a staticmethod, but rather simply del it at the end of the class body -- it's not meant to be used from outside the class in this case.