Re: decorators tutorials
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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