Re: decorators tutorials

2009-03-23 Thread Scott David Daniels

Josiah Carlson wrote:
... I try to limit my use of decorators whenever possible, both because I 
still have to support Python 2.3 (which doesn't support the syntax), and 
because I find that they obfuscate what the code is doing more often 
than not.  I will admit that they are useful as a metaprogramming 
technique.  Just be careful.


I find them very useful in debugging (for example writing a decorator
'traced'), and have also used them to simplify code that puts a lot
of functions into a dictionary.  In the latter case, the function can
be returned unadorned, or can be stored, and only the locater for the
function returned:

function_table = []
def enumerated(function):
function_table.append(function)
return len(function_table) - 1

@enumerated
def triple(a, b, c):
blah, blah, blah

@enumerated
def double(a, b):
blah, blah, blah

@enumerated
def another(a, b, c):
blah, blah, blah

After all of that, the identifiers triple, double, and another refer
to 0, 1, and 2 respectively, and you can call functions with the
following structure:
function_table[double]('pi', 3.14)
This can be very useful for certain kinds of table-driven code (where
you may want to be able to efficiently store lists of functions to call
in data files).

--Scott David Daniels
scott.dani...@acm.org
--
http://mail.python.org/mailman/listinfo/python-list


Re: decorators tutorials

2007-07-25 Thread Josiah Carlson
james_027 wrote:
 hi bruno,
 
 That seems to be hard to read at all, or I am just very new to python?

No, it's hard to read.  Note that it's not, technically, necessary to 
use nested functions to get the same results as a particular decorator. 
  For example, earlier you provided...

def check_login(func):
 def _check_login(*args):
 print I am decorator
 return func(*args)
 return _check_login

That could be written as...

class check_login:
 def __init__(self, func):
 self.func = func
 def __call__(self, *args):
 print I am decorator
 return self.func(*args)

The latter class-based method is a bit clunkier, but I find that it's 
easier to understand and unravel after the fact (you can also add your 
own __repr__ method for useful introspection).


 With that decorator how do I take advantage of it compare when I just
 write a function that could do the same as what the decorator did? I
 could translate the could from above into ...
 
 def check_login(msg):
#...
 def my_func(toto, tata):
#...
 
 #call it like this
 check_login('msg')
 my_func('toto', 'tata')

There are many uses for decorators (I'm sure others have posted about 
them already), and really, the syntax is a convenience meant to reduce 
the number of times you need to type the same string...

@long_decorator
def realy_long_function_name():
 ...

rather than...

def realy_long_function_name():
 ...
realy_long_function_name = long_decorator(realy_long_function_name)


I try to limit my use of decorators whenever possible, both because I 
still have to support Python 2.3 (which doesn't support the syntax), and 
because I find that they obfuscate what the code is doing more often 
than not.  I will admit that they are useful as a metaprogramming 
technique.  Just be careful.

  - Josiah
-- 
http://mail.python.org/mailman/listinfo/python-list


decorators tutorials

2007-07-23 Thread james_027
Hi,

I am learning python by learning django, and I stumble upon decorator
which is very cool, any beginners resources for python decorators,
although I can google it, I just want to get a good tutorial for this
topic.

Thanks
james

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: decorators tutorials

2007-07-23 Thread Bruno Desthuilliers
james_027 a écrit :
 Hi,
 
 I am learning python by learning django, and I stumble upon decorator
 which is very cool, any beginners resources for python decorators,
 although I can google it, I just want to get a good tutorial for this
 topic.

You should find answers on python.org, and searching this newsgroup.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: decorators tutorials

2007-07-23 Thread Michele Simionato
On Jul 23, 10:13 am, james_027 [EMAIL PROTECTED] wrote:
 Hi,

 I am learning python by learning django, and I stumble upon decorator
 which is very cool, any beginners resources for python decorators,
 although I can google it, I just want to get a good tutorial for this
 topic.

 Thanks
 james

Look at the decorator page in the Python Wiki. There is also a paper
by
David Mertz on IBM DeveloperWorks. Finally, you may have a look at my
own work http://www.phyast.pitt.edu/~micheles/python/documentation.html

   Michele Simionato

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: decorators tutorials

2007-07-23 Thread [EMAIL PROTECTED]
james_027 wrote:
 Hi,

 I am learning python by learning django, and I stumble upon decorator
 which is very cool, any beginners resources for python decorators,
 although I can google it, I just want to get a good tutorial for this
 topic.

Decorators are just a more concise but less obvious way of calling a
defined function on another function.

e.g.
@my_decorator
def foo():
   ...

is the essentially the same as:

def foo():
   ...
foo=my_decorator(foo)

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: decorators tutorials

2007-07-23 Thread Roel Schroeven
james_027 schreef:
 Hi,
 
 I am learning python by learning django, and I stumble upon decorator
 which is very cool, any beginners resources for python decorators,
 although I can google it, I just want to get a good tutorial for this
 topic.

I like the short explanation on Kent's Korner: 
http://personalpages.tds.net/~kent37/kk/1.html

-- 
If I have been able to see further, it was only because I stood
on the shoulders of giants.  -- Isaac Newton

Roel Schroeven
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: decorators tutorials

2007-07-23 Thread Bruno Desthuilliers
james_027 a écrit :
 Hi all,
 
 I am having difficulty understanding decorator. The definition was
 clear for me, but the syntax is not so clear to me.
 
 will decorators will always have to be in this way
 
 def check_login(func):
 def _check_login(*args):
 print I am decorator
 return func(*args)
 return _check_login
 

Sort of... Well, depends...

Basically, a decorator is a callable taking a callable as argument and 
returning a callable. These callable are usually *but* not necessarily 
functions. You may want to read the section about the special method 
__call__ in the  Fine Manual.

Also, you may want to write a 'parameterized' decorator - a decorator 
taking arguments. In this case, you need one more wrapping level:

def check_login(msg):
   def check_login_deco(func):
 def _check_login(*args, **kw):
   print msg
   return func(*args, **kw)
 return _check_login
   return check_login_deco

@check_login(I am the decorator)
def my_func(toto, tata):
   print toto, tata


-- 
http://mail.python.org/mailman/listinfo/python-list


Re: decorators tutorials

2007-07-23 Thread james_027
Hi all,

I am having difficulty understanding decorator. The definition was
clear for me, but the syntax is not so clear to me.

will decorators will always have to be in this way

def check_login(func):
def _check_login(*args):
print I am decorator
return func(*args)
return _check_login



@check_login
def method2(input):
print I am method TWO. Input %s % input


james

On Jul 23, 4:41 pm, [EMAIL PROTECTED] [EMAIL PROTECTED] wrote:
 james_027 wrote:
  Hi,

  I am learning python by learning django, and I stumble upon decorator
  which is very cool, any beginners resources for python decorators,
  although I can google it, I just want to get a good tutorial for this
  topic.

 Decorators are just a more concise but less obvious way of calling a
 defined function on another function.

 e.g.
 @my_decorator
 def foo():
...

 is the essentially the same as:

 def foo():
...
 foo=my_decorator(foo)


-- 
http://mail.python.org/mailman/listinfo/python-list


Re: decorators tutorials

2007-07-23 Thread james_027
hi bruno,

That seems to be hard to read at all, or I am just very new to python?

With that decorator how do I take advantage of it compare when I just
write a function that could do the same as what the decorator did? I
could translate the could from above into ...

def check_login(msg):
   #...
def my_func(toto, tata):
   #...

#call it like this
check_login('msg')
my_func('toto', 'tata')

Thanks
james
On Jul 23, 6:26 pm, Bruno Desthuilliers bruno.
[EMAIL PROTECTED] wrote:
 james_027 a écrit :

  Hi all,

  I am having difficulty understanding decorator. The definition was
  clear for me, but the syntax is not so clear to me.

  will decorators will always have to be in this way

  def check_login(func):
  def _check_login(*args):
  print I am decorator
  return func(*args)
  return _check_login

 Sort of... Well, depends...

 Basically, a decorator is a callable taking a callable as argument and
 returning a callable. These callable are usually *but* not necessarily
 functions. You may want to read the section about the special method
 __call__ in the  Fine Manual.

 Also, you may want to write a 'parameterized' decorator - a decorator
 taking arguments. In this case, you need one more wrapping level:

 def check_login(msg):
def check_login_deco(func):
  def _check_login(*args, **kw):
print msg
return func(*args, **kw)
  return _check_login
return check_login_deco

 @check_login(I am the decorator)
 def my_func(toto, tata):
print toto, tata


-- 
http://mail.python.org/mailman/listinfo/python-list

Re: decorators tutorials

2007-07-23 Thread Ben Finney
james_027 [EMAIL PROTECTED] writes:

 Hi all,

(Please don't top-post your reply. Instead, remove from the quoted
material all the parts that are irrelevant to your reply, and post
underneath what you're responding to, in normal chronological order
like any other discussion.)

 I am having difficulty understanding decorator. The definition was
 clear for me, but the syntax is not so clear to me.
 
 will decorators will always have to be in this way
 
 def check_login(func):
 def _check_login(*args):
 print I am decorator
 return func(*args)
 return _check_login
 
 @check_login
 def method2(input):
 print I am method TWO. Input %s % input

That looks okay. What is unclear?

-- 
 \I went to court for a parking ticket; I pleaded insanity. I |
  `\   said 'Your Honour, who in their right mind parks in the passing |
_o__)lane?'  -- Steven Wright |
Ben Finney
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: decorators tutorials

2007-07-23 Thread james_027
Hi,

  def check_login(func):
  def _check_login(*args):
  print I am decorator
  return func(*args)
  return _check_login

  @check_login
  def method2(input):
  print I am method TWO. Input %s % input

 That looks okay. What is unclear?


It just look complicated than using a simple function like this
def check_login(msg):
   #...
def my_func(toto, tata):
   #...

#call it like this
check_login('msg')
my_func('toto', 'tata')

I hope I could be able to understand clearly the decorators and use it
to it efficiently

Thanks
james

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: decorators tutorials

2007-07-23 Thread Diez B. Roggisch
james_027 wrote:

 hi bruno,
 
 That seems to be hard to read at all, or I am just very new to python?
 
 With that decorator how do I take advantage of it compare when I just
 write a function that could do the same as what the decorator did? I
 could translate the could from above into ...
 
 def check_login(msg):
#...
 def my_func(toto, tata):
#...
 
 #call it like this
 check_login('msg')
 my_func('toto', 'tata')

A decorator can alter the function _in place_ - it is not neccessary to
alter code that calls my_func, as your example does. 

As an additional benefit, it separates concerns - my_func does some stuff,
but mixing it with login-related logic is cumbersome:

def my_func(parameters):
if not logged_in():
   do some redirection
do_the_real_work()

is much more error-prone than

@check_login
def my_func(parameters):
   do_the_real_work()

because then you can just skim the decorator and concentrate on the actual
code.

What one often reaches with decorators is something referred to as aspect
orientied programming. 

Diez
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: decorators tutorials

2007-07-23 Thread Bruno Desthuilliers
james_027 a écrit :
 hi bruno,
 
 That seems to be hard to read at all, or I am just very new to python?

or just new to higher order functions ? (ie: functions working on 
functions).

 With that decorator how do I take advantage of it compare when I just
 write a function that could do the same as what the decorator did? I
 could translate the could from above into ...
 
 def check_login(msg):
#...
 def my_func(toto, tata):
#...
 
 #call it like this
 check_login('msg')
 my_func('toto', 'tata')

The first (and already very important difference) is that, with your 
solution, you have to remember to explicitely call check_login before 
calling my_func, while the decorator will take care of this. This allow 
to factor out orthogonal behaviours (like permission management, logging 
etc). Now there are almost endless other possible uses - anything that 
requires adding metadata to functions (CherryPy's way of flagging 
request handlers), registering functions for later use (ie: entry points 
for a plugin system, rule-based dispatch etc), triggering other 
behaviours before and/or after the function call - possibly bypassing 
the call to the original function, etc, etc, etc.

Note that the important part here is not the @decorator syntax - which 
is just (nice) syntactic sugar - but the ability to use higher order 
functions.

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: decorators tutorials

2007-07-23 Thread Jason
On Jul 23, 2:13 am, james_027 [EMAIL PROTECTED] wrote:
 Hi,

 I am learning python by learning django, and I stumble upon decorator
 which is very cool, any beginners resources for python decorators,
 although I can google it, I just want to get a good tutorial for this
 topic.

 Thanks
 james

Remember that functions in Python are created when their containing
scope is parsed.  Let's suppose you want a way to help you debug
function calls.  This should catch any uncaught exceptions, log a
message to the logging system, and start a pdb interpreter.  It should
allow the SystemExit exception to continue to propogate without doing
those actions.  The following example would do that appropriately:

def HelpDebug(func, *args, **keyargs):
Assist with debugging a function.
# The func argument is a Pythong function object
# arg is the positional arguments that follow the
# first parameter, and keyargs has the keyword arguments.
try:
returnValue = func(*args, **keyargs)
return returnValue
except SystemExit:
raise  # Reraise the system exit exception
except Exception, error:
from logging import DEBUG, log
from sys import exc_info
import pdb

log(DEBUG, Caught Exception: %s, error)
# Start the debugger at the place where the
# exception occurred
pdb.post_mortem(exc_info()[2])
return  # Nothing to return when an exception occurred

def DivXY(x, y):
Divides X by Y
return x / y


# Debug the following calls
HelpDebug(DivXY, 5.0, 2.1)  # This will succeed
HelpDebug(DivXY, 10.0, 0.0) # Causes a ZeroDivisionError exception

There's a serious problem, though.  If you'd like to remove the
debugging effect, you need to change all your HelpDebug(DivXY,
xvalue, yvalue) calls to DivXY(xvalue, yvalue).  Besides, you're
trying to get the result of DivXY, not HelpDebug.  The calling code
shouldn't care about HelpDebug at all.  We could do change HelpDebug
so it always calls DivXY, but then we need to create a new function
for each one we want to debug.

This is where nested scopes come in.  Other code should care about
calling DivXY, but not HelpDebug.  Furthermore, the caller shouldn't
be able to casually tell the difference between calling a regular
DivXY or the HelpDebug'ed DivXY.

Well, if the caller shouldn't be able to casually tell the difference
between DivXY with or without the debugging code, then we need to be
able to do the following:
value1 = DivXY(5.0, 2.1)   # The regular call
value2 = HelpDebugDivXY(5.0, 2.1)  # The debugged call

We could create a special HelpDebugDivXY function for every such
function, but that would quickly exhaust our patience, and introduce
lots of extra code that can have bugs.  Python has nested scoping,
though.  If you nest a function inside another function, the inner
function has access to the names in the outer function.

That doesn't sound too spectacular at first.  HOWEVER, in Python
functions are objects!  The outer function can return the inner
function object.  Even though the outer function has returned, /the
inner function still has access to the outer function's names/!  For
example:
 def GetPrintXFunc(x):
... Returns a function that takes no parameters, but prints the
argument
... # Inner function starts just below
... def PrintX():
...Prints the object bound to the name x in enclosing scope.
...print X is, x
... # A function object is now bound to the name PrintX
... return PrintX
...
 PrintSpam = GetPrintXFunc(Spam)
 PrintPi = GetPrintXFunc(3.14159)
 PrintSpam()
X is Spam
 PrintPi()
X is 3.14159


Both PrintSpam and PrintPi keep access to their enclosing scope's
arguments!  In Python, the def statement is actually a statement...
and IT ISN'T EVALUATED UNTIL ITS ENCLOSING SCOPE IS EXECUTED.

Take that in.  That is entirely unlike C or C++, where a function
definition is evaluated at compile time.  In Python, all statements
are evaluated at run time.  This works even for nested classes.
Here's the modified code to help us debug:

def WrapWithHelpDebug(func):
Returns a function object that transparently wraps the
parameter
with the HelpDebug function

# The def statement actually defines a function object and binds
# it to a name.  Since it is nested in this function, the def
# statement isn't evaluated until
def HelpDebug(*args, **keyargs):
Assist with debugging a function.
# The func argument is a Pythong function object
# arg is the positional arguments that follow the
# first parameter, and keyargs has the keyword arguments.
try:
# The name func comes from the outer scope,
WrapWithHelpDebug
returnValue = func(*args, **keyargs)
return returnValue
except SystemExit:
raise  # Reraise the system exit exception
except Exception, error:
from logging import DEBUG, log
from 

Re: decorators tutorials

2007-07-23 Thread Steve Holden
james_027 wrote:
 Hi,
 
 def check_login(func):
 def _check_login(*args):
 print I am decorator
 return func(*args)
 return _check_login
 @check_login
 def method2(input):
 print I am method TWO. Input %s % input
 That looks okay. What is unclear?

 
 It just look complicated than using a simple function like this
 def check_login(msg):
#...
 def my_func(toto, tata):
#...
 
 #call it like this
 check_login('msg')
 my_func('toto', 'tata')
 
 I hope I could be able to understand clearly the decorators and use it
 to it efficiently
 
Unfortunately your example isn't equivalent to the decorator version. 
The decorator syntax actually calls the decorator function using the 
following function as its argument, then replaces the function 
definition on with the result of the call on the decorator.

Your example just calls two functions one after the other without any 
relationship being established between them.

regards
  Steve
-- 
Steve Holden+1 571 484 6266   +1 800 494 3119
Holden Web LLC/Ltd   http://www.holdenweb.com
Skype: holdenweb  http://del.icio.us/steve.holden
--- Asciimercial --
Get on the web: Blog, lens and tag the Internet
Many services currently offer free registration
--- Thank You for Reading -

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: decorators tutorials

2007-07-23 Thread Jason
On Jul 23, 11:25 am, Jason [EMAIL PROTECTED] wrote:
 On Jul 23, 2:13 am, james_027 [EMAIL PROTECTED] wrote:

  Hi,

  I am learning python by learning django, and I stumble upon decorator
  which is very cool, any beginners resources for python decorators,
  although I can google it, I just want to get a good tutorial for this
  topic.

  Thanks
  james

With apologies, there is an error in my previous WrapWithHelpDebug.
The last part of the function should read:
# Back in the WrapWithHelpDebug scope.
# HelpDebug is now a function objected defined in this scope.
return HelpDebug  # This line was missing


Now, my prior post shows how decorators work.  Functions are objects
created by Python's def statement.  They have access to the names in
all their enclosing scopes: the module's global scope and any
functions that they are nested in.

The WrapWithHelpDebug decorator wraps a function so uncaught
exceptions get caught, logged, and the Python debugger is started.
You won't notice much output from the logger usually, because the
default log level is set to DEBUG.  That might be fine, but maybe
you want to pass the debugging level as a parameter.

import logging

def WrapWithHelpDebug(func, logLevel):
Returns a function object that transparently wraps the
parameter
with the HelpDebug function

# The def statement actually defines a function object and binds
# it to a name.  Since it is nested in this function, the def
# statement isn't evaluated until
def HelpDebug(*args, **keyargs):
Assist with debugging a function.
# The func argument is a Pythong function object
# arg is the positional arguments that follow the
# first parameter, and keyargs has the keyword arguments.
try:
# The name func comes from the outer scope,
WrapWithHelpDebug
returnValue = func(*args, **keyargs)
return returnValue
except SystemExit:
raise  # Reraise the system exit exception
except Exception, error:
from logging import log
from sys import exc_info
import pdb

log(logLevel, Caught Exception: %s, error)
# Start the debugger at the place where the
# exception occurred
pdb.post_mortem(exc_info()[2])
return  # Nothing to return when an exception occurred

# Back in the WrapWithHelpDebug scope.
# HelpDebug is now a function objected defined in this scope.
return HelpDebug

def DivXY(x, y):
Divides X by Y
return x / y
DivXY = WrapWithHelpDebug(DivXY, logging.DEBUG)

# Debug the following calls
DivXY(5.0, 2.1)  # This will succeed
DivXY(10.0, 0.0) # Causes a ZeroDivisionError exception

So, if we just need to add a new parameter, how do we do that with a
decorator?  Could we use @WrapWithHelpDebug(logging.DEBUG)?

No.  Remember, the decorator symbol is just a bit of syntactic sugar.
It turns:
@WrapWithHelpDebug(logging.DEBUG)
def DivXY(x, y):
Divides X by Y
return x / y

Into:
def DivXY(x, y):
Divides X by Y
return x / y
DivXY = WrapWithHelpDebug(logging.DEBUG)(DivXY)

Oops!  That implies that we're calling WrapWithHelpDebug with our
logging parameter.  To accommodate the extra parameter, we're going to
need to use Python's nested scopes again.  Here's a final version that
does everything we want:

import logging

def HelpDebugDecorator(logLevel):
Returns a function object that will properly decorate a
function.

# Note that logLevel used in the nested function HelpDebug
# comes from this scope.

def WrapWithHelpDebug(func):
Returns a function object that transparently wraps the
parameter
with the HelpDebug function

# The def statement actually defines a function object and
binds
# it to a name.  Since it is nested in this function, the def
# statement isn't evaluated until
def HelpDebug(*args, **keyargs):
Assist with debugging a function.
# The func argument is a Pythong function object
# arg is the positional arguments that follow the
# first parameter, and keyargs has the keyword arguments.
try:
# The name func comes from the outer scope,
WrapWithHelpDebug
returnValue = func(*args, **keyargs)
return returnValue
except SystemExit:
raise  # Reraise the system exit exception
except Exception, error:
from logging import log
from sys import exc_info
import pdb

log(logLevel, Caught Exception: %s, error)
# Start the debugger at the place where the
# exception occurred
pdb.post_mortem(exc_info()[2])
return  # Nothing to return when an exception occurred

# Back in the WrapWithHelpDebug scope.
# HelpDebug is now a function objected