Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #29160

Re: Decorators not worth the effort

From Ulrich Eckhardt <ulrich.eckhardt@dominolaser.com>
Newsgroups comp.lang.python
Subject Re: Decorators not worth the effort
Date 2012-09-14 13:49 +0200
Message-ID <c6ibi9-0n3.ln1@satorlaser.homedns.org> (permalink)
References <mailman.690.1347614888.27098.python-list@python.org>

Show all headers | View raw


Am 14.09.2012 11:28, schrieb Jean-Michel Pichavant:
> Decorators are very popular so I kinda already know that the
> fault is mine. Now to the reason why I have troubles writing
> them, I don't know. Every time I did use decorators, I spent
> way too much time writing it (and debugging it).
>
> I wrote the following one, used to decorate any function that access
> an equipment, it raises an exception when the timeout expires. The
> timeout is adapted to the platform, ASIC of FPGA so people don't need
> to specify everytime one timeout per platform.
>
> In the end it would replace
>
> def boot(self, timeout=15):
>      if FPGA:
>          self.sendCmd("bootMe", timeout=timeout*3)
>      else:
>          self.sendCmd("bootMe", timeout=timeout)
>
> with
>
> @timeout(15)
> def boot(self, timeout=None):
>      self.sendCmd("bootMe", timeout)
>
> I wrote a nice documentation with sphinx to explain this, how to use
> it, how it can improve code. After spending hours on the decorator +
> doc, feedback from my colleagues : What the F... !!

Quite honestly: I think like your colleagues in this case and that in 
this case the decorator doesn't improve the code. Instead, I would 
probably have added a _get_timeout() function that takes care of 
adjusting the argument passed to the function according to the 
underlying hardware target.

To be less abstract, the particular problem I have with your approach is 
that I can't even guess what your code means, let alone what parameters 
it actually takes. If you had written

   @default_timeout(15)
   def boot(self, timeout=None):

instead, I would have been able to guess. OTOH, then again I would have 
wondered why you used a decorator to create a default argument when 
there is builtin support for specifying default arguments for functions.

Maybe you could get away with a decorator like this:

   @adjust_timeout
   def boot(self, timeout=2.5):

The idea is that the decorator modifies the timeout value passed to the 
function (or maybe just modifies the default value?) according to the 
underlying hardware.


> Decorators are very python specific (probably exists in any dynamic
> language though, I don't know), in some environment where people need
> to switch from C to python everyday, decorators add python magic that
> not everyone is familiar with.

The same could be said for classes, iterators, significant whitespace, 
docstrings, lambdas. I think that this was just a bad example but it 
doesn't prove that decorators are worthless. Decorators are useful tools 
if they do something to a function, like doing something before or after 
the actual code, or modifying the context in which the code is called. 
Just setting a default parameter is possible as you have proved, but 
it's IMHO not a good use case.

A bit more specific to your case, adding a timeout decorator would 
actually make much more sense if it transparently invoked the actual 
function in a second thread and the calling thread stops waiting for 
completion and raises an error after that timeout. This has the distinct 
advantage that the code doing the actual communication doesn't have any 
timeout handling code inside.

I'm currently doing something similar here though I only monitor a TCP 
connection that is used for some telnet-style requests. Every function 
making a request over TCP is decorated with @_check_connection. That 
decorator does two things:
1. It checks for an existing fatal connection error.
2. It runs the request and filters resulting errors for fatal connection 
errors.

The decorator looks like this:

def _check_connection(fn):
     @functools.wraps(fn)
     def wrapper(self, *args, **kwargs):
         # check for sticky connection errors
         if self._connection_error:
             raise self._connection_error
         # run actual function
         try:
             return fn(self, *args, **kwargs)
         catch RequestFailed:
             # The other side signalled a failure, but
             # further requests can still succeed.
             raise
         catch ConnectionError, e:
             # The connection is broken beyond repair.
             # Store sticky connection and forward.
             self._connection_error = e
             raise
     return wrapper

I have had other programmers here write such requests and they blindly 
copied the decorator from existing code. This works because the code 
inside that converts/formats/parses the inputs and outputs is completely 
unaware of the connection monitoring. Otherwise, I don't think anyone 
could explain what this decorator does, but they don't have to 
understand it either. It just works.

I wish you a nice weekend!

Uli

Back to comp.lang.python | Previous | NextPrevious in thread | Find similar | Unroll thread


Thread

Re: Decorators not worth the effort Jean-Michel Pichavant <jeanmichel@sequans.com> - 2012-09-14 11:28 +0200
  Re: Decorators not worth the effort Duncan Booth <duncan.booth@invalid.invalid> - 2012-09-14 11:26 +0000
    Re: Decorators not worth the effort andrea crotti <andrea.crotti.0@gmail.com> - 2012-09-14 15:12 +0100
    Re: Decorators not worth the effort Chris Angelico <rosuav@gmail.com> - 2012-09-15 00:41 +1000
      Re: Decorators not worth the effort 88888 Dihedral <dihedral88888@googlemail.com> - 2012-09-14 09:37 -0700
      Re: Decorators not worth the effort 88888 Dihedral <dihedral88888@googlemail.com> - 2012-09-14 09:37 -0700
    Re: Decorators not worth the effort andrea crotti <andrea.crotti.0@gmail.com> - 2012-09-14 17:15 +0100
    Re: Decorators not worth the effort Chris Angelico <rosuav@gmail.com> - 2012-09-15 03:30 +1000
      Re: Decorators not worth the effort Neil Cerutti <neilc@norwich.edu> - 2012-09-18 13:19 +0000
        Re: Decorators not worth the effort Chris Angelico <rosuav@gmail.com> - 2012-09-18 23:25 +1000
          Re: Decorators not worth the effort 88888 Dihedral <dihedral88888@googlemail.com> - 2012-09-18 08:14 -0700
          Re: Decorators not worth the effort 88888 Dihedral <dihedral88888@googlemail.com> - 2012-09-18 08:14 -0700
    RE: Decorators not worth the effort "Prasad, Ramit" <ramit.prasad@jpmorgan.com> - 2012-09-14 23:14 +0000
  Re: Decorators not worth the effort Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2012-09-14 12:01 +0000
    Re: Decorators not worth the effort Tim Chase <python.list@tim.thechases.com> - 2012-09-14 08:06 -0500
      Re: Decorators not worth the effort Steve Howell <showell30@yahoo.com> - 2012-09-14 18:13 -0700
  Re: Decorators not worth the effort Ulrich Eckhardt <ulrich.eckhardt@dominolaser.com> - 2012-09-14 13:49 +0200

csiph-web