views:

129

answers:

1

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?

+6  A: 

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
Pär Wieslander
This works even better because `self` isn't used in both function definitions.
Colorado
@EShull: Actually, `decor` can be a static method, despite the `self` reference. `self` is only referenced inside `increment()`, and when invoking `f.add(10)` on a `foo` instance, the `self` parameter inside `increment()` will reference `f`, and the increment will work as expected.
Pär Wieslander
This looks like it'll work. Gotta leave work but if it does, I'm going to flag this as the answer. Thanks!
wheaties