[Tutor] Writing decorators?

Alan G alan.gauld at yahoo.co.uk
Tue Jul 5 13:26:00 EDT 2016


   Sorry for top posting, but yes excepting you don't need the parens after
   log in the @log line.

   Sent from my Fonepad

   Alex Hall <ahall at autodist.com> wrote:

   Okay, I think I follow. So a decorator to log that a function ran might
   be:

   import utils

   @log()
   def run():
   ** #do things

   #utils.py

   logger = #set up logging

   def log(f):
   ** def logThatFRan(*args, **kwargs):
   ****** [1]logger.info("running %s" %(f.__name__)
   ****** return f(*args, **kwargs)
   ** return logThatFRan

   That will log that F ran, then run f with any arguments. I know I'd have
   to decorate the inner function with functools.wraps for __name__ to work
   correctly, but that's the general idea, right?
   On Tue, Jul 5, 2016 at 10:40 AM, Alan Gauld via Tutor
   <[2]tutor at python.org> wrote:

     On 05/07/16 14:22, Alex Hall wrote:

     > To simplify things, what might be an example of a decorator that, say,
     > prints "decorated" before whatever string the decorated function
     prints?

     > My attempt would be:
     >
     > def prependDecorated(f):
     >** **def prepend():
     >** ** **return "decorated"+f()
     >** **#something should go at this level too?

     Recall that a decorator is:

     a function
     that takes a function as its argument
     and returns a function

     Your code fails on the third item.

     Lets take a trivial example first, a decorator that
     does nothing. Define a function that takes a function
     and returns the same function untouched:

     >>> def donothing(f): return f

     Now apply it to a square() function:

     >>> @donothing
     def square(x): return x*x

     >>> square
     <function square at 0x7f3633fcb0d0>
     >>> square(4)
     16

     We could do the same without the @ shorthand by using

     square2 = donothing(square)

     But the @ syntax makes it more readable.

     Now lets look at your task
     We need a function that takes a function and
     returns a function that prepends a string:

     def prepend(f):
     ** ** def add_string(*args, **kwargs):** # in case f takes arguments
     ** ** ** ** return "decorated "+ str(f(*args,**kwargs))
     ** ** return add_string

     Now we can apply that to a function

     @prepend
     def cube(n): return n*n*n

     cube(3)

     I'm biased because I was the tech editor but the book
     Professional Python has a nice chapter on decorators.

     HTH

     --
     Alan G
     Author of the Learn to Program web site
     [3]http://www.alan-g.me.uk/
     [4]http://www.amazon.com/author/alan_gauld
     Follow my photo-blog on Flickr at:
     [5]http://www.flickr.com/photos/alangauldphotos

     _______________________________________________
     Tutor maillist** -** [6]Tutor at python.org
     To unsubscribe or change subscription options:
     [7]https://mail.python.org/mailman/listinfo/tutor

   --
   Alex Hall
   Automatic Distributors, IT department
   [8]ahall at autodist.com

References

   Visible links
   1. http://logger.info/
   2. mailto:tutor at python.org
   3. http://www.alan-g.me.uk/
   4. http://www.amazon.com/author/alan_gauld
   5. http://www.flickr.com/photos/alangauldphotos
   6. mailto:Tutor at python.org
   7. https://mail.python.org/mailman/listinfo/tutor
   8. mailto:ahall at autodist.com


More information about the Tutor mailing list