By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
439,957 Members | 1,969 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 439,957 IT Pros & Developers. It's quick & easy.

Decorators inside of class and decorator parameters

P: n/a
MR
Hello All,

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:

-how I would pass arguments into the fooDecorator if I wanted to (my
various attempts have failed)
-what the difference is between decorating with @fooDecorator versus
@fooDecorator()
-why does this code even work, because the first argument to
fooDecorator isn't self

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?

Jan 13 '07 #1
Share this Question
Share on Google+
7 Replies


P: n/a
"MR" <pt**********@gmail.comescribió en el mensaje
news:11**********************@l53g2000cwa.googlegr oups.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...mentation.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

Jan 14 '07 #2

P: n/a
Gabriel Genellina wrote:
see this article by M. Simoniato
http://www.phyast.pitt.edu/~micheles...mentation.html for a better
way using its decorator factory.
Actually the name is Simionato ;)
I have just released version 2.0, the new thing is an update_wrapper
function similar to the one
in the standard library, but with the ability to preserve the signature
on demand. For instance

def traced(func):
def wrapper(*args, **kw):
print 'calling %s with args %s, %s' % (func, args, kw)
return func(*args, **kw)
return update_wrapper(wrapper, func, create=False)

works exactly as functools.update_wrapper (i.e. copies__doc__,
__module__,etc. from func to wrapper without
preserving the signature), whereas update_wrapper(wrapper, func,
create=True) creates a new wrapper
with the right signature before copying the attributes.

Michele Simionato

Jan 14 '07 #3

P: n/a
Gabriel Genellina wrote:
[snip]
As said in the beginning, there is no use for decorators as methods (perhaps
someone can find a use case?)
Except, perhaps to indicate to the script reader that the decorator only
applies within the class?

Colin W.
If you move the example above inside the class, you get exactly the same
results.

HTH,

Jan 14 '07 #4

P: n/a
"Colin J. Williams" <cj*@sympatico.caescribió en el mensaje
news:eo**********@sea.gmane.org...
Gabriel Genellina wrote:
>As said in the beginning, there is no use for decorators as methods
(perhaps
someone can find a use case?)
Except, perhaps to indicate to the script reader that the decorator only
applies within the class?
But it looks rather strange - a method without self, that is not a
classmethod nor static method, and can't be called on an instance...

--
Gabriel Genellina

Jan 14 '07 #5

P: n/a
"Michele Simionato" <mi***************@gmail.comescribió en el mensaje
news:11**********************@51g2000cwl.googlegro ups.com...
Gabriel Genellina wrote:
>see this article by M. Simoniato
http://www.phyast.pitt.edu/~micheles...mentation.html for a
better
way using its decorator factory.

Actually the name is Simionato ;)
Oh, sorry! I think I've written it wrong in another place too :(

--
Gabriel Genellina

Jan 14 '07 #6

P: n/a
MR
Thanks so much for your reply. You've definitely helped me a great
deal on this. Your comment about the difference between define time and
instantiation time cleared things up more than anything, and that also
helped clear up the confusion I was having about "self".

I think the places I've seen decorators called like fooDecorator() must
be using some default arguments in the function signature...so that
part makes a lot more sense now too.

Thanks again!
Gabriel Genellina wrote:
"MR" <pt**********@gmail.comescribió en el mensaje
news:11**********************@l53g2000cwa.googlegr oups.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 whichit
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...mentation.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
Jan 14 '07 #7

P: n/a
MR
Wow. Really neat stuff there. memoize seems especially cool since you
can get lots of nice dynamic programming benefits "for free" (sorry if
I just stated the obvious, but I thought was was especially cool.)
Michele Simionato wrote:
Gabriel Genellina wrote:
see this article by M. Simoniato
http://www.phyast.pitt.edu/~micheles...mentation.html for a better
way using its decorator factory.

Actually the name is Simionato ;)
I have just released version 2.0, the new thing is an update_wrapper
function similar to the one
in the standard library, but with the ability to preserve the signature
on demand. For instance

def traced(func):
def wrapper(*args, **kw):
print 'calling %s with args %s, %s' % (func, args, kw)
return func(*args, **kw)
return update_wrapper(wrapper, func, create=False)

works exactly as functools.update_wrapper (i.e. copies__doc__,
__module__,etc. from func to wrapper without
preserving the signature), whereas update_wrapper(wrapper, func,
create=True) creates a new wrapper
with the right signature before copying the attributes.

Michele Simionato
Jan 14 '07 #8

This discussion thread is closed

Replies have been disabled for this discussion.