1. 12

  2. 6

    I’ve updated this based on @KevinMGranger and @hwayne’s comments.

    Once again, lobste.rs comments have helped make my writing better. Starting to be tempted to post thing first here, wait for comments, update appropriately, and only then post elsewhere.

    1. 3

      The complaint about the signature was fixed in python3.4.

      1. 2

        Thanks for correction!. I wonder why I didn’t catch that when writing the post, I was using Python 3.5. Probably screwed up reloading the code or something. Will update post after dinner.

      2. 2

        add = synchronized(add) doesn’t preserve the docstring either, so at worst decorators are API-neutral.

        1. 2

          The point, which I will try to make more explicit, is that decorators are a wasted opportunity: it could’ve done the right thing in the language level, but instead it forces library code to fix the edge cases the language doesn’t handle for you.

          1. 2

            I can see two reasons why the current behavior is preferable:

            1. Explicit is better than implicit. If it automatically switched the docstring, it would make decorations have a different behavior from manually wrapping a function, which adds magic.
            2. What would be the expected behavior for functions that return decorators? For example, you don’t write @lru_cache, you write @lru_cache().

            Edit: another case is if you explicitly want to do something with the docstring, like make a depreciated decorator. This would be a lot harder if decorators automatically used the wrapped functions attributes.

            1. 5

              Responding respectively:

              1. It’s not like @something is particularly explicit. It’s a language feature that does a thing, seems reasonable that it would do some other things too.
              2. Not sure that’s relevant? In the end you’re returning a function, and that is what gets mutated.
              3. Could’ve been solved with different syntax. Current syntax is not ideal. The decorator factory case always confuses me :)

              More broadly: decorators were added in 2.4. functools.wraps was added in 2.6. So fundamentally the use case of callers wasn’t addressed by Python all until then.