Search code examples
pythonpython-3.xclasspython-decoratorsattributeerror

Python Decorator cannot access called method


I am trying to write a decorator for a method that will call a second method. When I run the code I receive the error:
AttributeError: 'Backoff' object has no attribute 'formatter'

Simplified, the code is:

class Backoff:
    def __init__(self, f):
        self.f = f

    def __call__(self, *args, **kwargs):
        n = 1
        while n < 11:
            try:
                return self.f(self, *args, **kwargs)
            except FooError as e:
                <handle error>
                time.sleep((2 ** n) + (random.randint(0, 1000) / 1000))
                n = n + 1

class SomeClass:
    def __init__(self):
        pass
    @Backoff
    def first_method(self, foo, bar):
        return self.formatter(foo, bar)

    def formatter(self, x, y):
        return some_function_to_format(x, y)

How can I pass the second method to the first method in a way that the decorator can recognise it?

Any help would be amazing!


Solution

  • You are passing a method to Backoff, assigning it as an instance variable, and then calling it. This not bound to an instance until it is being called in Backoff.__call__, where it is then bound to an instance of Backoff which does not have a formatter property.

    There might be a straightforward solution to this depending on what your instance method needs access to (i.e. if it only needs to reference a class or static method, it can just call the fully qualified name directly). However, if you need the instance method to reference an instance property, I would suggest not using a class decorator at all. Using a function decorator will not run into these issues, you can create a closure and return a function with the same call signature.