Live data from Hacker News

A primer on Python decorators

thumbtack.com

31–40 of 45 posts

Re: A primer on Python decorators

#31
post #20
post #16

To authors: I would avoid try except in this code snippet, a simple if else is more explicit. I would also avoid a = b = c statement. One line per statement is better most of the time.

The Python community generally advocates an "it's easier to ask for forgiveness than permission" coding style. When faced with a condition of the form "if condition a holds, do b, else c", it's very often a better idea to do "let's try b, and do c in case b fails because condition a didn't hold". In this case it's better because you can avoid computing an extra hash of the object in cases where it's already a key of…

Out of curiosity, in a situation where you are doing negligible condition testing, is try–except still considered "more performant" than if–else flow control? For some reason (and I'm going to do so reading to get clarity on this point), I have had the silly notion that throwing and handling exceptions can be costly.

Re: A primer on Python decorators

#32

Nice description of method decorators. Didn't touch on class decorators, or decorators that can decorate both classes and methods (arguably very ugly wrapper functions that return decorators that decorate).

Wrote a post a while ago that talks about them - http://hangar.runway7.net/decorators-wrappers-python

Re: A primer on Python decorators

#33
Nice description. I'd suggest explaining how decorators that accept arguments (i.e. @memcached('some-arg')) work lest it befuddle some beginner. It is not straightforward (the first argument of a decorator is the function being decorated).

Re: A primer on Python decorators

#34
post #31
post #20

Earlier quoted context omitted.

The Python community generally advocates an "it's easier to ask for forgiveness than permission" coding style. When faced with a condition of the form "if condition a holds, do b, else c", it's very often a better idea to do "let's try b, and do c in case b fails because condition a didn't hold". In this case it's better because you can avoid computing an extra hash of the object in cases where it's already a key of…

Out of curiosity, in a situation where you are doing negligible condition testing, is try–except still considered "more performant" than if–else flow control? For some reason (and I'm going to do so reading to get clarity on this point), I have had the silly notion that throwing and handling exceptions can be costly.

[deleted]

Re: A primer on Python decorators

#35
post #31
post #20

Earlier quoted context omitted.

The Python community generally advocates an "it's easier to ask for forgiveness than permission" coding style. When faced with a condition of the form "if condition a holds, do b, else c", it's very often a better idea to do "let's try b, and do c in case b fails because condition a didn't hold". In this case it's better because you can avoid computing an extra hash of the object in cases where it's already a key of…

Out of curiosity, in a situation where you are doing negligible condition testing, is try–except still considered "more performant" than if–else flow control? For some reason (and I'm going to do so reading to get clarity on this point), I have had the silly notion that throwing and handling exceptions can be costly.

I don't think the try-except is 'more performant'. At least from the below benchmark test it doesn't seem to be so.

  >>> from timeit import timeit
  >>> timeit(setup='x=dict([(i,i*2) for i in range(10)])',stmt=
       """
          if 20 in x:
             pass""")

  0.07420943164572691

  >>> timeit(setup='x=dict([(i,i*2) for i in range(10)])',
       stmt="""
               try:
		  x[20]
               except KeyError:
		  pass""")

  1.1514457843105674

Re: A primer on Python decorators

#37
post #16

To authors: I would avoid try except in this code snippet, a simple if else is more explicit. I would also avoid a = b = c statement. One line per statement is better most of the time.

I'm no pythonist, but I think setdefault would be perfect for the case

http://docs.python.org/library/stdtypes.html#dict.setdefault

Re: A primer on Python decorators

#38
post #7

What I really want to know is how a framework such as Flask uses a decorator for the route. How is the correct function picked for a particular route that is defined against the decorator? (Maybe I'm completely misunderstanding this...)

Some might say it's a dangerous abuse of decorators. Since decorators (generally) run at module load time, any stateful decorator (usually) implies the use of global mutable state, which is (considered by many to be) the root cause of much bad design, convoluted flow, limited reusability and untestability. This is perhaps why most decorators in the standard library are pure (off the top of my head). This is well beyo…

While you're right it is an easy to make mistake with decorators, I don't think the issue is global mutable state as much as uncontrolled mutable state, especially if used against singleton.

Typically, doing this:

    @register
    def foo():
    ….
is bad, but this is much better:

    @registry.register
    def foo():
    …
if registry is a global object that is not a singleton. In that case, you can easily use distinct registries (for testing, etc…) and this is not much of an issue in practice. Another way of doing this kind of things is to post_pone the registration, with the decorator just labelling things:

    @register
    def foo():
    …

    def register(f):
        return WrappedFunc(f)
and then build an explicit list of modules being imported, and look for every instance of WrappedFunc in that module locals(). I use this in my own packaging project where people can define multiple python scripts that hook into different stages of the packaging.

Re: A primer on Python decorators

#39
post #35
post #31

Earlier quoted context omitted.

Out of curiosity, in a situation where you are doing negligible condition testing, is try–except still considered "more performant" than if–else flow control? For some reason (and I'm going to do so reading to get clarity on this point), I have had the silly notion that throwing and handling exceptions can be costly.

I don't think the try-except is 'more performant'. At least from the below benchmark test it doesn't seem to be so. >>> from timeit import timeit >>> timeit(setup='x=dict([(i,i*2) for i in range(10)])',stmt= """ if 20 in x: pass""") 0.07420943164572691 >>> timeit(setup='x=dict([(i,i*2) for i in range(10)])', stmt=""" try: x[20] except KeyError: pass""") 1.1514457843105674

I am on my phone and cannot test this, but the try:except: construct is optimised for the non-exceptional path. The latter is probably faster for x[0] than x[20].

Re: A primer on Python decorators

#40
post #16

To authors: I would avoid try except in this code snippet, a simple if else is more explicit. I would also avoid a = b = c statement. One line per statement is better most of the time.

The try/except is the preferred python way of doing things. In Python, try/except is cheap, and in the case where the try actually succeeds, you can gain a slight performance benefit. In this case, since performance is the goal, it is perfect for memoize.
Post reply on HN