Decorating class member functions

Virgil Dupras hardcoded.software at gmail.com
Thu May 3 22:03:57 EDT 2007


On May 3, 9:21 pm, Andy Terrel <andy.ter... at gmail.com> wrote:
> Okay does anyone know how to decorate class member functions?
>
> The following code gives me an error:
>
> Traceback (most recent call last):
>   File "decorators2.py", line 33, in <module>
>     s.update()
>   File "decorators2.py", line 13, in __call__
>     retval = self.fn.__call__(*args,**kws)
> TypeError: update() takes exactly 1 argument (0 given)
>
> ------------------
>
> #! /usr/bin/env python
>
> class Bugger (object):
>     def __init__ (self, module, fn):
>         self.module = module
>         self.fn = fn
>
>     def __call__ (self,*args, **kws):
>         ret_val = self.fn(*args,**kws)
>         return ret_val
>
> def instrument (module_name):
>     ret_val = lambda x: Bugger(module_name, x)
>     return ret_val
>
> class Stupid:
>     def __init__(self):
>         self.val = 1
>
>     @instrument("xpd.spam")
>     def update(self):
>         self.val += 1
>
> s = Stupid()
> s.update()

Second attempt. After some fuss around, I think it's just not possible
to have a class instance as a decorator. the self gets lost in
translation.

#! /usr/bin/env python
class Caller(object):
    def __init__ (self, fn):
        self.fn = fn

    def __call__(self, *args, **kwargs):
        print 'Caller calling!', repr(args)
        return self.fn(*args, **kwargs)

def mydecorator(f):
    return Caller(f)

class Stupid:
    def __init__(self):
        self.val = 1

    @mydecorator
    def update(self):
        self.val += 1

s = Stupid()
s.update()

Caller calling! ()
Traceback (most recent call last):
  File "/Users/hsoft/Desktop/foo.py", line 22, in ?
    s.update()
  File "/Users/hsoft/Desktop/foo.py", line 8, in __call__
    return self.fn(*args, **kwargs)
TypeError: update() takes exactly 1 argument (0 given)

But why do you want to use a class? If you want to have a decorator
with argument, you only need to have something like:

def instrument(module):
    def decorator(f):
        def wrapper(*args, **kwargs):
            print module
            return f(*args, **kwargs)
        return wrapper
    return decorator




More information about the Python-list mailing list