Archive

Archive for May, 2010

python: static methods and the class decorator

May 2nd, 2010 No comments

When one uses a class decorator python wraps the class definition like this:

class RegisterExposedMethods (object):
    def __init__(self, decoratedClass, registry):
        self._decoratedClass = decoratedClass

    def __call__(self,*__args,**__kw):
        return self._decoratedClass(*__args,**__kw)

@RegisterExposedMethods
class MyClass (object):
    def __init__(self):
        object.__init__(self)

    @staticfunction
    def stat (blah):
        print "blah: %s" % blah

A = RegisterExposedMethods (MyClass)

If you write the class decorator like I did, this has 2 major problems in it:

1.) static function stat will not be accessible
2.) in stack traces the class MyClass is named like the decorator function RegisterExposedMethods

You can see both problems in this stack trace:

<function coolFunction at 0x018C9630>
Traceback (most recent call last):
File "class_decorator.py", line 37, in <module>
MyClass.stat()
AttributeError: 'RegisterExposedMethods' object has no attribute 'stat'

To solve the two issues I’ve added the following to my decorator:

class RegisterExposedMethods (object):
    def __init__(self, decoratedClass):
        self._decoratedClass = decoratedClass
        # cloak us as the original class (problem 2.)
        self.__class__.__name__ = decoratedClass.__name__

    def __call__(self,*__args,**__kw):
        print "RegisterExposedMethods.call"
        return self._decoratedClass(*__args,**__kw)

    # define a getattr function to get the static function from the decorated class
    def __getattr__(self, name):
        return getattr(self._decoratedClass, name)

The problem with 1.) is that the class definition is wrapped. With that in place the static method is searched firstly on the decorator class
and not on the decorated class.

Categories: python Tags: