On 12 December 2011 13:27, Henrik Faber <hfa...@invalid.net> wrote: > Hi group, > > I'm a bit confused regarding decorators. Recently started playing with > them with Python3 and wanted (as an excercise) to implement a simple > type checker first: I know there are lots of them out there, this is > actually one of the reasons I chose that particular function (to compare > my solution against other, proven solutions). > > Starting with a blank slate, I did something along the lines of: > > class _TypeCheckedFunction(): > def __init__(self, decoratedfunction): > self._decoratedfunction = decoratedfunction > > def __call__(self, *args, **kwargs): > [...] Actual checking > > def typecheck(wrappedfunction): > checkfunction = _TypeCheckedFunction(wrappedfunction) > functools.update_wrapper(checkfunction, wrappedfunction) > return checkfunction > > And decorate my methods like > > @typecheck > def setbar(self, bar: str): > > This works somewhat. The problem is, however, when the method is > actually called. This is what happens: > > 1. The decorator is called upon import of the decorated class. It > creates a _TypeCheckedFunction(setbar) object. > 2. When setbar is actually called (blubb.setbar("fooobar")), the > __call__ method of the previously created _TypeCheckedFunction is invoked. > 3. When trying to call self._decoratedfunction from within that object, > this fails: "self" is missing! self._decoratedfunction is only the > *function*, not the bound function of the object that contains setbar(). > Therefore I cannot proceed here. > > Solutions that I have seen working usually consist of two functions > wrapped in each other, but I do not know why the additional introduction > of a class makes everything fail. > > Can someone please enlighten me?
You can (need to?) use the descriptor protocol to deal with methods. from functools import partial class _TypeCheckedFunction(): def __init__(self, decoratedfunction): self._decoratedfunction = decoratedfunction def __call__(self, *args, **kwargs): [...] Actual checking def __get__(self, obj, objtype): return partial(self, obj) (Untested) HTH -- Arnaud -- http://mail.python.org/mailman/listinfo/python-list