Python decorators in classes Python decorators in classes python python

Python decorators in classes


Would something like this do what you need?

class Test(object):    def _decorator(foo):        def magic( self ) :            print "start magic"            foo( self )            print "end magic"        return magic    @_decorator    def bar( self ) :        print "normal call"test = Test()test.bar()

This avoids the call to self to access the decorator and leaves it hidden in the class namespace as a regular method.

>>> import stackoverflow>>> test = stackoverflow.Test()>>> test.bar()start magicnormal callend magic>>> 

edited to answer question in comments:

How to use the hidden decorator in another class

class Test(object):    def _decorator(foo):        def magic( self ) :            print "start magic"            foo( self )            print "end magic"        return magic    @_decorator    def bar( self ) :        print "normal call"    _decorator = staticmethod( _decorator )class TestB( Test ):    @Test._decorator    def bar( self ):        print "override bar in"        super( TestB, self ).bar()        print "override bar out"print "Normal:"test = Test()test.bar()printprint "Inherited:"b = TestB()b.bar()print

Output:

Normal:start magicnormal callend magicInherited:start magicoverride bar instart magicnormal callend magicoverride bar outend magic


What you're wanting to do isn't possible. Take, for instance, whether or not the code below looks valid:

class Test(object):    def _decorator(self, foo):        foo()    def bar(self):        pass    bar = self._decorator(bar)

It, of course, isn't valid since self isn't defined at that point. The same goes for Test as it won't be defined until the class itself is defined (which its in the process of). I'm showing you this code snippet because this is what your decorator snippet transforms into.

So, as you can see, accessing the instance in a decorator like that isn't really possible since decorators are applied during the definition of whatever function/method they are attached to and not during instantiation.

If you need class-level access, try this:

class Test(object):    @classmethod    def _decorator(cls, foo):        foo()    def bar(self):        passTest.bar = Test._decorator(Test.bar)


import functoolsclass Example:    def wrapper(func):        @functools.wraps(func)        def wrap(self, *args, **kwargs):            print("inside wrap")            return func(self, *args, **kwargs)        return wrap    @wrapper    def method(self):        print("METHOD")    wrapper = staticmethod(wrapper)e = Example()e.method()