18
votes

Help a guy out. Can't seem to get a decorator to work with inheritance. Broke it down to the simplest little example in my scratch workspace. Still can't seem to get it working.

class bar(object):
    def __init__(self):
        self.val = 4
    def setVal(self,x):
        self.val = x
    def decor(self, func):
        def increment(self, x):
            return func( self, x ) + self.val
        return increment

class foo(bar):
    def __init__(self):
        bar.__init__(self)
    @decor
    def add(self, x):
        return x

Oops, name "decor" is not defined.

Okay, how about @bar.decor? TypeError: unbound method "decor" must be called with a bar instance as first argument (got function instance instead)

Ok, how about @self.decor? Name "self" is not defined.

Ok, how about @foo.decor?! Name "foo" is not defined.

AaaaAAaAaaaarrrrgggg... What am I doing wrong?

2
In your example, you could have return x + self.val for the definition of add in foo. Could you not do this in you actual code? - Gary Kerr
This is a distilled example code highlighting the issue I was facing. If the code were that simple, then yes. However, it's not. - wheaties

2 Answers

20
votes

Define decor as a static method and use the form @bar.decor:

class bar(object):
    def __init__(self):
        self.val = 4
    def setVal(self,x):
        self.val = x
    @staticmethod
    def decor(func):
        def increment(self, x):
            return func(self, x) + self.val
        return increment

class foo(bar):
    def __init__(self):
        bar.__init__(self)
    @bar.decor
    def add(self, x):
        return x
0
votes

I know the question has been asked 11 years ago ...

I had the same problem, here is my solution to use an inherited private decorator :

class foo:
    def __bar(func):
        def wrapper(self):
            print('beginning')
            func(self)
            print('end')
        return wrapper

class baz(foo):
    def __init__(self):
        self.quux = 'middle'
    @foo._foo__bar
    def qux(self):
        print(self.quux)

a = baz()
a.qux()

The output is :

beginning
middle
end