Re: function decorators
On 9/28/2010 6:02 PM, Nick Donohue wrote: I came across this code just now: def time_me(function): def wrap(*arg): start = time.time() r = function(*arg) end = time.time() print "%s (%0.3f ms)" %(function.func_name, (end-start)*1000) return wrap @time_me def some_function(somearg) As others noted, this is an bad example of a decorator. Please forget it. Let us move on... #deco def func_name(*args): pass is syntactic sugar for (which is to say, is almost and for practical purposes is exactly equivalent to) def func_name(*args): pass func_name = deco(func_name) Indeed, Python did well without them until they were added. But there are 2 advantages of the decorator syntax: 1. Without it, one write (and read!) func_name 3 times instead of 1. One of the use cases that motivated decorators was a situation where someone was required to wrap numerous functions with stylized names about 30 chars long, like 'get_hopscotch_version_a_code_123x76' 2. Understanding the code may require that one know that it will never see the light of day as is. If the body is several lines, the wrapping call may be hard to see. To put it another way, the wrapping calls often belong near the doc string since they are part of a high-level overview of the function. -- Terry Jan Reedy -- http://mail.python.org/mailman/listinfo/python-list
Re: function decorators
On Tue, Sep 28, 2010 at 4:02 PM, Nick Donohue wrote: > I came across this code just now: > > def time_me(function): > def wrap(*arg): >start = time.time() >r = function(*arg) >end = time.time() >print "%s (%0.3f ms)" %(function.func_name, (end-start)*1000) > return wrap > > @time_me > def some_function(somearg) > > some_function(arg) > > I've been looking online about what I think is going on, and from what > I can tell this code is using function decorators. > > I guess what I'm asking is if someone could tell me what exactly is > going on in this code - how is it different from passing: > time_me(some_function(123))? I've tried it this way and it works. > Not quite. It's actually equivalent to calling time_me(some_function)(123). > why would I use these? wouldn't it be more flexible to not write the > decorator before the function definition, so I could choose to wrap it > or not? > In general, yes. In the particular case above, I don't know why it would have been written as a decorator, unless it was merely meant to be toy code. Generally I'll use a decorator in order to add common functionality that is critical to the function's operation. Dynamically adding a default keyword argument is one example that comes to mind, or wrapping the function in a context manager without adding indentation to the entire function body. Also, decorators can also be used for things besides wrapping functions, such as registering them with a framework. Cheers, Ian -- http://mail.python.org/mailman/listinfo/python-list
Re: function decorators
Nick Donohue writes: > I came across this code just now: > > def time_me(function): > def wrap(*arg): > start = time.time() > r = function(*arg) > end = time.time() > print "%s (%0.3f ms)" %(function.func_name, (end-start)*1000) > return wrap > > @time_me > def some_function(somearg) > > some_function(arg) > > I've been looking online about what I think is going on, and from what > I can tell this code is using function decorators. > > I guess what I'm asking is if someone could tell me what exactly is > going on in this code - how is it different from passing: > time_me(some_function(123))? I've tried it this way and it works. This is *not* what the decorator is doing. The equivalent of a decorator and then calling the result is this: >>> some_function = time_me(some_function) >>> some_function(123) Notice the difference? The decorator (a badly written one, by the way - it doesn't deal with a possible return value and keyword args) wraps the function into time measuring code. In general, a decorator is a callable that takes one argument. And whatever that callable returns is then bound under the same name as the original function (or class, since python 2.6 I believe) Which is what >>> some_function = time_me(some_function) actually does. So decorator syntax with the @ is really just that - a bit of syntactic sugar. > why would I use these? wouldn't it be more flexible to not write the > decorator before the function definition, so I could choose to wrap it > or not? Of course it's more flexible to do whatever the decorator does only if you need it. If you need that, it's a sign of a misuse of decorators. Their strength is in making boiler-plate code run without you having to type it out all the time. E.g. putting transactional boundaries around some code that deals with a database. Checking for proper authentication and authorization. Uniformely deal with exceptions. And so forth. Amongst the more popular decorators in python are the classmethod and property decorators. Go look them up in the stdlib. Diez -- http://mail.python.org/mailman/listinfo/python-list
Re: function decorators
On 2010-09-28, Nick Donohue wrote: > why would I use these? wouldn't it be more flexible to not write the > decorator before the function definition, so I could choose to wrap it > or not? The utility is that it lets you modify all calls to a function at once, without changing all the instances in a ton of source code. -s -- Copyright 2010, all wrongs reversed. Peter Seebach / usenet-nos...@seebs.net http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated! I am not speaking for my employer, although they do rent some of my opinions. -- http://mail.python.org/mailman/listinfo/python-list
function decorators
I came across this code just now: def time_me(function): def wrap(*arg): start = time.time() r = function(*arg) end = time.time() print "%s (%0.3f ms)" %(function.func_name, (end-start)*1000) return wrap @time_me def some_function(somearg) some_function(arg) I've been looking online about what I think is going on, and from what I can tell this code is using function decorators. I guess what I'm asking is if someone could tell me what exactly is going on in this code - how is it different from passing: time_me(some_function(123))? I've tried it this way and it works. why would I use these? wouldn't it be more flexible to not write the decorator before the function definition, so I could choose to wrap it or not? thanks -- http://mail.python.org/mailman/listinfo/python-list
Re: Function decorators
Aigars Aigars schrieb: Good day all, I am learning Python and came up to decorators. The question is: Why does function FoodList return value None? The code in attachment. Because the __call__ in Logger doesn't return the value of self.func. Diez -- http://mail.python.org/mailman/listinfo/python-list
Re: Function decorators
In article <[EMAIL PROTECTED]>, Aigars Aigars <[EMAIL PROTECTED]> wrote: > Good day all, I am learning Python and came up to decorators. The question > is: Why does function FoodList return value None? Because the function doesn't return anything, and in Python a function that doesn't explicitly return anything returns None. > The code in attachment. Thanks for not just pasting it into the post, like so: class Logger: def __init__(self, function): self.func = function def __call__(self, *args, **kwargs): print "Function %s called with args = %s, kwargs = %s" % (self.func.__name__, str(args), str(kwargs)) self.func(*args, **kwargs) @Logger def FoodList(a, b, c="spam"): text = "Food is %s, %s, %s" % (a, b, c) print text return text if __name__ == "__main__": a = FoodList("eggs", "potatoes") print a > Thank you, > Aigars- > [Image] -- David C. Ullrich -- http://mail.python.org/mailman/listinfo/python-list
Re: Function decorators
Aigars Aigars wrote: Good day all, I am learning Python and came up to decorators. The question is: Why does function FoodList return value None? The code in attachment. Thank you, Aigars -- http://mail.python.org/mailman/listinfo/python-list First of all, you should always inherit from "object" whenever it is possible. Then the answer: you did not return the result. Instead of self.func(*args, **kwargs) use this: return self.func(*args, **kwargs) Corrected example attached. Best, Laszlo class Logger(object): def __init__(self, function): self.func = function def __call__(self, *args, **kwargs): print "Function %s called with args = %s, kwargs = %s" % (self.func.__name__, str(args), str(kwargs)) return self.func(*args, **kwargs) # Return is important here! @Logger def FoodList(a, b, c="spam"): text = "Food is %s, %s, %s" % (a, b, c) print text return text if __name__ == "__main__": a = FoodList("eggs", "potatoes") print a -- http://mail.python.org/mailman/listinfo/python-list
Function decorators
Good day all, I am learning Python and came up to decorators. The question is: Why does function FoodList return value None? The code in attachment. Thank you, Aigars testingVarLogger.py Description: application/unknown-application-x-python -- http://mail.python.org/mailman/listinfo/python-list