Hacker News new | ask | show | jobs
by ramnes 3078 days ago
This notebook should be named "how to abuse decorators". Honestly, there is very little here that you want to use in a real project.

I completely agree in that saying "a decorator is a function that takes a function and returns a function" isn't technically correct since you can do much more than just that; but for readability, maintainability and other real world purposes, you might want to keep to that definition.

6 comments

> This notebook should be named "how to abuse decorators". Honestly, there is very little here that you want to use in a real project.

Annotation, registration, dispatch and verification are pretty much the most common uses for decorators. If using decorators for these is bad, then decorators aren't needed at all: function wrapping is much more rarely used than those other four, and would not warrant an additional syntax construct.

Annotation and registration are indeed common and proper uses of decorators.

What I dislike are mostly the inputs 8, 9, 13, 14, and 23 that could give nasty ideas to an inexperienced developer, while a more experienced developer wouldn't need them to understand that a decorator is just a syntactic sugar and that, yes, "applying a decorator d to a function x [is] the same as writing the definition of x, then x = d(x)" (which the author seems to refute).

I understand that those examples are solely intended to show that "it works", but they aren't educational to me.

I disagree. From the end section of "real-world usage examples", there is this library https://github.com/mrocklin/multipledispatch/ that implements "Decorators for registration. It's used in at least one (probably many more) serious open-source project that I know of: GPflow https://github.com/GPflow/GPflow/blob/master/gpflow/expectat... .

"Decorators for preconditions" look pretty neat as well. It's a little sad that the preconditions themselves have to be written inside strings though.

"Decorators for preconditions" indeed looks neat, reminds me of Clojure which has both preconditions and postconditions built in.
> It's a little sad that the preconditions themselves have to be written inside strings though.

Isn’t it possible to pass a lambda instead?

Yes. Lambdas in Python are awkward, but you can definitely use either a lambda or a named function.

In fact, you could define a number of useful precondition functions in a single module and use them throughout a project. A couple of higher-order functions could make the post's examples safer and nicer-looking too. For example:

    @precondition(starts_with('The year is '))
where the starts_with precondition is:

    def starts_with(param):
        def test(s):
            return s.startswith(param)
        return test
> Lambdas in Python are awkward

Can you elaborate on that, please?

Considering the examples given by the author, I think they would be a better option.

Not the OP but I think he was referring to the restrictions python puts on lambda expressions:

- they can only contain a single expression

- they cannot contain statements

Python has lambdas that have multiple expressions and statements.

They're called functions.

For precondition checking, shouldn’t that suffice?
I've used that multipledispatch, along my own homegrown version, in production systems.
See my comment above. And yes, the preconditions could be written with a lambda, which would be much cleaner than using eval.
I've used decorators for registration multiple times in the real world. It's nice to be able to visibly attach the registration function call to the object you are registering rather than having it just written after it somewhere.
The @route decorator in Flask has only the side effect of registering a route with the function as handler. I prefer to have a map for big projects where I can see with a glance what routes directs to what functions, but for getting started and for little projects I find it nice and reasonable.
I disagree. Actually I am not a big fan of decorators since for me they tend to obscure WTF is going on in other people's code I'm reading. However, I quite liked the section "Decorators for verification" -- I hadn't seen that use case before and it seems handy to me.
Technically a better definition would be -- "A decorator is a callable object which takes in a callable object and returns a callable object" but I agree that it is much easier wrapping one's head around it when the callable object is a function and decorator just acts as syntactic sugar for higher order functions.
No, if you read the article, you can learn that a decorator is a callable which can return ANYTHING, not just callables.
Thanks, I stand corrected :) That makes me wonder , I have not been able to imagine a usecase for it when it doesn't return a callable, the article doesn't help in that regard either. Got some thinking to do I guess.
the article mention multiple examples, one of being the "registering things" when it returns the same function untouched, just put away the function instance in a list or something to use it later.
Returning a function would be returning a callable object, which is what I was alluding to. The section under "Decorator Toolbox" contains no suggested usecases for returning a non-callable object, will try and think of something.