On Thu, 24 Feb 2005 15:00:46 -0700, Steven Bethard
<[EMAIL PROTECTED]> wrote:
> Tom Willis wrote:
> > Question on decorators in general. Can you parameterize those?
> >
> > If I wanted to something and after the function call for example, I
> > would expect something like this would work.
> >
> > def prepostdecorator(function,pre,post):
> >     def wrapper(*args,**kwargs):
> >         pre()
> >         result =  function(*args,**kwargs)
> >         post()
> >         return result
> >     return wrapper
> >
> > def dopre():
> >     print "call pre"
> >
> > def dopost():
> >     print "call post"
> >
> > @prepostdecorator(pre,post)
> > def sayhello(Name):
> >     print "Hey %s, nice to meet you" % Name
> >
> > #sayhello = prepostdecorator(sayhello,dopre,dopost)
> >
> > if __name__=="__main__":
> >     sayhello("Dude")
> >
> > but I get ...
> > TypeError: prepostdecorator() takes exactly 3 arguments (2 given)
> 
> You get this TypeError for the same reason that I get the following
> TypeError:
> 
> py> def prepostdecorator(function, pre, post):
> ...     pass
> ...
> py> prepostdecorator(1, 2)
> Traceback (most recent call last):
>    File "<interactive input>", line 1, in ?
> TypeError: prepostdecorator() takes exactly 3 arguments (2 given)
> 
> The expression after @ is a _normal Python expression_.  So since you
> couldn't call prepostdecorator with 2 arguments in any other situation,
> you still can't.
> 
> If you want to call prepostdecorator with 2 arguments, you need to write
> it this way.  A few options:
> 
> (1) Use nested functions:
> 
> py> def prepostdecorator(pre,post):
> ...     def decorator(function):
> ...         def wrapper(*args,**kwargs):
> ...             pre()
> ...             result =  function(*args,**kwargs)
> ...             post()
> ...             return result
> ...         return wrapper
> ...     return decorator
> ...
> py> @prepostdecorator(dopre, dopost)
> ... def sayhello(name):
> ...     print "Hey %s, nice to meet you" % name
> ...
> py> sayhello('Tom')
> call pre
> Hey Tom, nice to meet you
> call post
> 
> (2) Use functional.partial (PEP 309[1])
> 
> py> def prepostdecorator(pre, post, function):
> ...     def wrapper(*args,**kwargs):
> ...         pre()
> ...         result =  function(*args,**kwargs)
> ...         post()
> ...         return result
> ...     return wrapper
> ...
> py> @partial(prepostdecorator, dopre, dopost)
> ... def sayhello(name):
> ...     print "Hey %s, nice to meet you" % name
> ...
> py> sayhello('Tom')
> call pre
> Hey Tom, nice to meet you
> call post
> 
> (3) Use a class:
> 
> py> class prepostdecorator(object):
> ...     def __init__(self, pre, post):
> ...         self.pre, self.post = pre, post
> ...     def __call__(self, function):
> ...         def wrapper(*args,**kwargs):
> ...             self.pre()
> ...             result = self.function(*args,**kwargs)
> ...             self.post()
> ...             return result
> ...         return wrapper
> py> @prepostdecorator(dopre, dopost)
> ... def sayhello(name):
> ...     print "Hey %s, nice to meet you" % name
> ...
> py> sayhello('Tom')
> call pre
> Hey Tom, nice to meet you
> call post
> 
> Note that in all of the above cases, the result of evaluating the
> expression after the @ is a callable object that takes _exactly one_
> argument, the function to be decorated.
> 
> HTH,
> 
> STeVe
> 
> [1] http://www.python.org/peps/pep-0309.html
> --
> http://mail.python.org/mailman/listinfo/python-list
> 
Wow thanks for the explanation!! Some of it is a bit mind bending to
me at the moment , but I'm going to mess with it a bit.



-- 
Thomas G. Willis
http://paperbackmusic.net
-- 
http://mail.python.org/mailman/listinfo/python-list

Reply via email to