Re: function decorators

2010-09-28 Thread Terry Reedy

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

2010-09-28 Thread Ian Kelly
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

2010-09-28 Thread Diez B. Roggisch
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

2010-09-28 Thread Seebs
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

2010-09-28 Thread Nick Donohue
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

2008-09-04 Thread Diez B. Roggisch

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

2008-09-04 Thread David C. Ullrich
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

2008-09-04 Thread Laszlo Nagy

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

2008-09-04 Thread Aigars Aigars
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