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!
Oh, don't do that! In __get__ put return self.__class__(self.func.__get__(obj))
ReplyDeleteAssigning to self.obj will lead to terrible bugs if used with one class and multiple instances, as the instances will keep overwriting each other.
Oops! Thanks for the correction.
ReplyDelete