Decorate class method with another class method

Viewed 35

Say I have a class, and I want to decorate one of its methods with another. Like in the example:

class Foobar:
    def foo(self, func):
        def wrapped(*args, **kwargs):
             print(self + " is doing something")
             func(*args, **kwargs)
        return wrapped
    @foo
    def bar(self, *args, **kwargs):
        print("Foobar")

Of course, when I make an instance of Foobar and run bar, an exception will be raised because the function gets passed to self and there's nothing for func. But I can't just decorate foo with staticmethod because self is needed to run the wrapped function.

This is quite a dilemma. Can someone help?

1 Answers

You can't have self in the foo() method, but you can get it just by specifying it in the wrapped() function:

class Foobar:
    def foo(func):
        print('foo is running')
        def wrapped(self, *args, **kwargs):
            print(str(self) + " is doing something")
            func(self, *args, **kwargs)
        return wrapped
    @foo
    def bar(self, *args, **kwargs):
        print("Foobar")
        print(self, args, kwargs)

print('Make Foobar')
f = Foobar()
f.bar(1, f=42)
print('Done')

Just to be clear, I've added some print() statements so you can see the order of operations:

foo is running
Make Foobar
<__main__.Foobar object at 0x03BE5210> is doing something
Foobar
<__main__.Foobar object at 0x03BE5210> (1,) {'f': 42}
Done
Related