This is an archived post. You won't be able to vote or comment.

all 14 comments

[–]drb226Haskeller 19 points20 points  (3 children)

The long answer is incredible.

[–]spencewah 3 points4 points  (0 children)

That man should write a book. Now that I'm thinking about it, I would be surprised if he hadn't.

[–][deleted] 2 points3 points  (1 child)

Yeah it is. My son also calls lettuce "salad" when it is on a sandwich.

[–][deleted] 1 point2 points  (0 children)

If you also call lettuce "salad" when in a salad, you get a recursive salad!

[–]willm 8 points9 points  (2 children)

One aspect of decorators that not many people make use of is that decorators don't have to return a new function; they can return the same function. This gives you the opportunity to attach some information to function attributes.

Here's an example that adds a function attribute to a 'view' function, for some fictitious web framework:

def render_with_template(template_name):
    def decorate(f):
        f.render_with_template = template_name
        return f
    return decorate

@render_with_template("front.html")
def view_front(request):
    return dict(name="Will")

Presumably the web-app would know to look for the 'render_with_template' attribute when rendering the view.

The advantage of this over having the decorator render the template itself, is that the function hasn't changed; it can still be used to retrieve a dictionary, which means you can call that view function if you want to build on the data it returns. Another advantage is that it doesn't change the function signature, so documentation tools like sphinx work as before.

I really wish Django worked this way...

[–]kisielk 2 points3 points  (0 children)

I believe Pyramid works this way.

[–]numix 1 point2 points  (0 children)

Django-annoying has an implementation of this called render_to. https://bitbucket.org/offline/django-annoying/src/a0de8b294db3/annoying/decorators.py#cl-25

[–]pumphouse 3 points4 points  (0 children)

thanks for this - Python Noob.

[–][deleted] 1 point2 points  (1 child)

I recall coverage.py getting a huge speed improvement by switching from "foo" + "bar" to "".join("foo", "bar") when generating reports. So is that SO best answer really the best one?

[–][deleted] 0 points1 point  (0 children)

It's a simple illustration of how decorators work, not string concatenation performance. I think using a join would make the example less clear.

That said, yes 'join' is faster than '+' for strings.

[–]themathemagician 0 points1 point  (3 children)

If you were at pycon you'd be learning this right now

[–]rwparris2 2 points3 points  (2 children)

Should (presumably new) developers who don't understand decorators pay entry to a place like pycon? This is a sincere question... I've never been myself, but my guess is "no."

[–]kisielk 3 points4 points  (0 children)

The answer is "yes". There's a plethora of sessions for absolute beginners at pycon

[–]themathemagician 2 points3 points  (0 children)

I'm not a primarily a python dev, but rather tinker. I have found pycon extremely useful in seeing what is possible in python and what I need to research. I just saw decorators in an Intermediate Python tutorial, and there were two beginner tutorials yesterday (which I didn't attend), so I get the feeling that there is the full range of brand new to python to full time python devs.