decorator peculiarity
Fredrik Lundh
fredrik at pythonware.com
Sun Dec 19 11:31:42 EST 2004
Diez B. Roggisch wrote:
> However I've encountered one peculiarity that strikes me odd:
>
> When one writes a decorated function like this:
>
> @decorate
> def foo():
> pass
>
> the function decorate usually looks like this:
>
> def decorate(func):
> def _d(*args, **kwargs):
> do_something()
> # call func
> func(*args, **kwargs)
> return _d
>
> So the function decorator has to return a function that is bound to the name
> foo in the originating context (module or class) and gets the function
> passed as argument.
>
> But if I want my decorator to be parametrized, it looks like this:
>
> @decorate(arg)
> def foo():
> pass
>
> def decorate(arg):
> def f(func):
> def _d(*args, **kwargs):
> do_something(arg)
> # call func
> func(*args, **kwargs)
> return _d
>
> So what happens is that an decorater with arguments is called with these,
> returns a callable that then is called with foo, and the result is stored
> under foo.
the decorator itself must be a callable, so to create parameterized decorators,
you have to create a callable that returns a callable.
due to some weird obsession with nested functions and lexical scoping, most
decorator examples use functions inside functions inside functions, but you can
of course use a good old class instead:
class decorator:
def __init__(self, params):
# save the parameters
def __call__(self, func):
# decorate the function
return func
@decorator(params)
def func(...):
pass
or even:
class decorator:
def __init__(self, params):
# save the parameters
def __call__(self, func):
self.func = func
return self.handler
def handler(self, *args):
# do something
self.func(*args)
# do something
</F>
More information about the Python-list
mailing list