Jigar Tanna <poisonousratt...@gmail.com> writes: > where I came across a special case of using arguments with decorators
A decorator is a function which takes exactly one parameter, and returns a function based on that parameter. <URL:http://docs.python.org/glossary.html#term-decorator> <URL:http://docs.python.org/reference/compound_stmts.html#function> So a decorator always takes an argument: the function to be decorated. > Below is the code for memoization where I was looking at the > concept... […] > def memoize(get_key=get_key, cache=cache) : > def _memoize( function) : > print function > def __memoize(*args, **kw) : > key = get_key(function, *args, **kw) > try: > return cache[key] > except KeyError: > cache[key] = function( *args, **kw) > return cache[key] > return __memoize > return _memoize Note that the function ‘memoize’ is not a decorator. It's a decorator creator; it returns a decorator. That is, you pass this function zero, one, or two arguments, and it defines a new function with the name ‘_memoize’; *that* function is then returned. That function is the decorator, and will receive exactly one parameter when you decorate a function. > @memoize() ‘memoize()’ calls the ‘memoize’ function, which creates and returns the decorator. That return value is then used (because of the ‘@’ syntax) to decorate the function whose definition follows. > def factory(n) : > return n * n This function is created, and then immediately passed as the single argument to the decorator that ‘memoize()’ returned above. The return value from that decorator then gets bound to the name ‘factory’. (Side note: it's unfortunate the writer of ‘memoize’ didn't wrap the decorated function better. In this implementation, the resulting function will be bound to the name ‘factory’, but will consider its name to be ‘_memoize’. It will also lack the docstring of the ‘factory’ function. For a better way, see ‘functools.wraps’.) > coming across to certain views from people, it is not a good practice > to use decorators with arguments (i.e. @memoize() ) Correcting your mental model: those are not decorators. They are creating a decorator, by calling a function that returns a decorator. And if you've come across views that say there's something wrong with that, those views are mistaken. There are many good reasons to call a function to return a decorator, and “I get a different decorator depending on what arguments I give to this decorator-creator” is the pattern. > and instead it is good to just use @memoize. That wouldn't work in this case, of course, since the function ‘memoize’ is not a decorator: it doesn't take the function-to-be-decorated as an argument. In other cases where the decorator is available immediately as a defined function (e.g. ‘functools.partial’ or the built-in ‘property’), there is of course no problem using that. But it's not always the case that you have that decorator yet, and calling another function (with whatever arguments it needs) to create the decorator at the point where you need to use it is also fine. > Can any of you guys explain me advantages and disadvantages of using > each of them I hope that explains. -- \ “Men never do evil so completely and cheerfully as when they do | `\ it from religious conviction.” —Blaise Pascal (1623–1662), | _o__) Pensées, #894. | Ben Finney -- http://mail.python.org/mailman/listinfo/python-list