Decorators inside of class and decorator parameters

Gabriel Genellina gagsl-py at yahoo.com.ar
Sun Jan 14 05:07:00 CET 2007


"MR" <ptwobrussell at gmail.com> escribió en el mensaje 
news:1168728983.541526.202320 at l53g2000cwa.googlegroups.com...

> I have a question about decorators, and I think an illustration would
> be helpful. Consider the following simple class:
>
> #begin code
> class Foo:
>    def fooDecorator(f):
>        print "fooDecorator"
>
>        def _f(self, *args, **kw):
>            return f(self, *args, **kw)
>
>        return _f
>
>    @fooDecorator
>    def fooMethod(self):
>        print "fooMethod"
>
> f = Foo()
> f.fooMethod()
> #end of code
>
> This code runs, and actually serves my purpose. However, I'm a little
> confused about three things and wanted to try and work through them
> while I had the time to do so. I believe all of my confusion is related
> to the parameters related to the fooDecorator:

[I reordered your questions to make the answer a bit more clear]

> -why does this code even work, because the first argument to
> fooDecorator isn't self

fooDecorator is called when the class is *defined*, not when it's 
instantiated. `self` has no meaning inside it, neither the class to which it 
belongs (Foo does not even exist yet).
At this time, fooDecorator is just a simple function, being collected inside 
a namespace in order to construct the Foo class at the end. So, you get 
*exactly* the same effect if you move fooDecorator outside the class.

> -how I would pass arguments into the fooDecorator if I wanted to (my
> various attempts have failed)

Once you move fooDecorator outside the class, and forget about `self` and 
such irrelevant stuff, it's just a decorator with arguments.
If you want to use something like this:
   @fooDecorator(3)
   def fooMethod(self):
that is translated to:
   fooMethod = fooDecorator(3)(fooMethod)
That is, fooDecorator will be called with one argument, and the result must 
be a normal decorator - a function accepting a function an an argument and 
returning another function.

def outerDecorator(param):
  def fooDecorator(f):
    print "fooDecorator"

    def _f(self, *args, **kw):
        print "decorated self=%s args=%s kw=%s param=%s" % (self, args, kw, 
param)
        kw['newparam']=param
        return f(self, *args, **kw)

    return _f
  return fooDecorator

This is the most direct way of doing this without any help from other 
modules - see this article by M. Simoniato 
http://www.phyast.pitt.edu/~micheles/python/documentation.html for a better 
way using its decorator factory.

> -what the difference is between decorating with @fooDecorator versus
> @fooDecorator()
Easy: the second way doesn't work :)
(I hope reading the previous item you can answer this yourself)

> I'm searched the net and read the PEPs that seemed relevant, but I
> didn't see much about decorators inside of a class like this. Can
> anyone comment on any of these three things?
As said in the beginning, there is no use for decorators as methods (perhaps 
someone can find a use case?)
If you move the example above inside the class, you get exactly the same 
results.

HTH,

-- 
Gabriel Genellina 






More information about the Python-list mailing list