[Tutor] Writing decorators?

Alex Hall ahall at autodist.com
Tue Jul 5 13:31:04 EDT 2016


On Tue, Jul 5, 2016 at 1:26 PM, Alan G <alan.gauld at yahoo.co.uk> wrote:

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

For decorators, do you never include parentheses except for passing
arguments? It seems a bit odd to drop them if they'd be empty, given that
anywhere else doing so would return the function object rather than call
it. Yet, if arguments are passed, you include them like you would anywhere
else. Or am I misunderstanding it?

>
> 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):
>     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 <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
>> http://www.alan-g.me.uk/
>> http://www.amazon.com/author/alan_gauld
>> Follow my photo-blog on Flickr at:
>> http://www.flickr.com/photos/alangauldphotos
>>
>>
>> _______________________________________________
>> Tutor maillist  -  Tutor at python.org
>> To unsubscribe or change subscription options:
>> https://mail.python.org/mailman/listinfo/tutor
>>
>
>
>
> --
> Alex Hall
> Automatic Distributors, IT department
> ahall at autodist.com
>



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


More information about the Tutor mailing list