Bruno Desthuilliers a écrit :
robert2821 a écrit :

(snip - sorry, hit the 'send' button too soon)

def getdec(f):
   dec = decorator(f)
   return dec.docall


class decorator:
   def __init__ (self, f):
       self.f = f

   def docall (self, *a):
       return self.f(*a)

class test:
   @getdec
   def doit (self, message):
       print message

if __name__ == '__main__':
   foo = test ()
   foo.doit ('Hello, world')


I'm wondering if the following program should work. I think it
should print 'Hello, World', but instead it produces a
>>> TypeError. Is this a bug in decorators, a feature of them, or a
>>> mistake or misunderstanding on my part?

<ot>
Last point : post the whole error message and traceback if possible
</ot>

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/tmp/python-10426amG.py", line 19, in <module>
    foo.doit ('Hello, world')
  File "/usr/tmp/python-10426amG.py", line 10, in docall
    return self. f(*a)
TypeError: doit() takes exactly 2 arguments (1 given)


This has to do with how Python makes methods from functions. Your getdec function - which is the real decorator - returns a class instance, not another function. This actually prevents doit() to be wrapped in a method when looked up on a test instance, so doit doesn't receive the instance as first param (hence the error message).

Here's a working version of your code using new-style classes:

def getdec(f):
    dec = Decorator(f)
    return dec

class Decorator(object):
    def __init__ (self, f):
        self.f = f
        self.instance = None

    def __get__(self, instance, cls):
        self.instance = instance
        return self

    def __call__(self, *args):
        args = (self.instance,) + args
        return self.f(*args)

class Test(object):
    @ getdec
    def doit(self, message):
        print message

if __name__ == '__main__':
    foo = Test ()

FWIW, note that the getdec function here is useless - you'd have the same result directly applying the Decorator class as a decorator.

HTH
--
http://mail.python.org/mailman/listinfo/python-list

Reply via email to