Decorating methods - where do my arguments go?

Duncan Booth duncan.booth at invalid.invalid
Mon May 11 11:17:55 EDT 2009


Mikael Olofsson <mikael at isy.liu.se> wrote:

> George Sakkis decorator function solution seems to work equally well 
for 
> functions and methods. However, I prefer the cleaner encapsulation 
given 
> by a class. Based on those observations, I think I will use the 
> following approach:
> 
> >>> class test_decorator(object):
> ...     _inst = None
> ...     def __init__(self,func):
> ...         self._func = func
> ...     def __call__(self, *args):
> ...         print 'Decorator:', args
> ...         if self._inst is None:
> ...             print 'We seem to be decorating a function.'
> ...             self._func(*args)
> ...         else:
> ...             print 'We seem to be decorating a method.'
> ...             self._func(self._inst,*args)
> ...     def __get__(self, inst, cls):
> ...         self._inst = inst
> ...         return self
> ...

The __get__ method should be returning a new object, NOT modifying the 
state of the decorator. As written it will break badly and unexpectedly 
in a variety of situations:

>>> inst1 = cls()
>>> inst2 = cls()
>>> inst1, inst2
(<__main__.cls object at 0x011BC470>, <__main__.cls object at 
0x011BCC90>)
>>> m = inst1.meth
>>> m()
Decorator: ()
We seem to be decorating a method.
Method:    <__main__.cls object at 0x011BC470> ()
>>> inst2.meth()
Decorator: ()
We seem to be decorating a method.
Method:    <__main__.cls object at 0x011BCC90> ()
>>> m()
Decorator: ()
We seem to be decorating a method.
Method:    <__main__.cls object at 0x011BCC90> ()

or even this:

>>> inst1.meth(inst2.meth())
Decorator: ()
We seem to be decorating a method.
Method:    <__main__.cls object at 0x011BCC90> ()
Decorator: (None,)
We seem to be decorating a method.
Method:    <__main__.cls object at 0x011BCC90> (None,)



-- 
Duncan Booth http://kupuguy.blogspot.com



More information about the Python-list mailing list