Wednesday, August 4, 2010

Python: Decorate bound methods with class-based decorators

Found something really useful buried in the comments over on Ian Bicking's blog: A way to decorate bound methods using class-based decorators. The semantics are quite understandable, too:

class deco(object):
    def __init__(self, func):
        self.func = func
        self.obj = None

    def __call__(self, arg):
        return self.func(self.obj, arg)

    def __get__(self, obj, type=None):
        self.obj = obj
        return self

You have to store the bound object using __get__ because __call__ is passed the decorator as the first arg, not whatever object the method is bound to. Tricky.

Chris Jones developed this and also tested the performance and found it to be not too terrible. Huzzah!

2 comments:

  1. Oh, don't do that! In __get__ put return self.__class__(self.func.__get__(obj))

    Assigning to self.obj will lead to terrible bugs if used with one class and multiple instances, as the instances will keep overwriting each other.

    ReplyDelete
  2. Oops! Thanks for the correction.

    ReplyDelete