On Fri, 14 Sep 2012 15:16:47 -0600, Ian Kelly wrote: > If only there were a conceptually simpler way to do this. Actually, > there is. I give you: metadecorators! [code snipped but shown below] > Which I think is certainly easier to understand than the nested > functions approach.
Maybe for you, but to me it is a big ball of mud. I have no idea how this is supposed to work! At a quick glance, I would have sworn that it *can't* work, since simple_decorator needs to see multiple arguments but only receives one, the function to be decorated. And yet it does work: py> from functools import partial py> def make_wrapper(wrapper): ... return lambda wrapped: partial(wrapper, wrapped) ... py> @make_wrapper ... def simple_decorator(func, *args, **kwargs): ... print "Entering decorated function" ... result = func(*args, **kwargs) ... print "Exiting decorated function" ... return result ... py> @simple_decorator ... def my_function(a, b, c): ... """Doc string""" ... return a+b+c ... py> my_function(1, 2, 3) Entering decorated function Exiting decorated function 6 So to me, this is far more magical than nested functions. If I saw this in t requires me to hunt through your library for the "simple function buried in a utility module somewhere" (your words), instead of seeing everything needed in a single decorator factory function. It requires that I understand how partial works, which in my opinion is quite tricky. (I never remember how it works or which arguments get curried.) And the end result is that the decorated function is less debugging- friendly than I demand: it is an anonymous partial object instead of a named function, and the doc string is lost. And it is far from clear to me how to modify your recipe to use functools.wraps in order to keep the name and docstring, or even whether I *can* use functools.wraps. I dare say I could answer all those questions with some experimentation and research. But I don't think that your "metadecorator" using partial is *inherently* more understandable than the standard decorator approach: def simple_decorator2(func): @functools.wraps(func) def inner(*args, **kwargs): print "Entering decorated function" result = func(*args, **kwargs) print "Exiting decorated function" return result return inner This is no more complex than yours, and it keeps the function name and docstring. > Parameterized decorators are not much more > difficult this way. This function: [snip code] > And now we have a fancy parameterized decorator that again requires no > thinking about nested functions at all. Again, at the cost of throwing away the function name and docstring. I realise that a lot of this boils down to personal preference, but I just don't think that nested functions are necessarily that hard to grasp, so I prefer to see as much of the decorator logic to be in one place (a nested decorator function) rather than scattered across two separate decorators plus partial. -- Steven -- http://mail.python.org/mailman/listinfo/python-list