[Python-Dev] Adding functools.decorator

Nick Coghlan ncoghlan at gmail.com
Tue May 2 12:36:42 CEST 2006


Guido van Rossum wrote:
> On 4/30/06, Georg Brandl <g.brandl at gmx.net> wrote:
>> Guido van Rossum wrote:
>>> I expect that at some point people will want to tweak what gets copied
>>> by _update_wrapper() -- e.g. some attributes may need to be
>>> deep-copied, or personalized, or skipped, etc.
>> What exactly do you have in mind there? If someone wants to achieve this,
>> she can write his own version of @decorator.
> 
> I meant that the provided version should make writing your own easier
> than copying the source and editing it. Some form of subclassing might
> make sense, or a bunch of smaller functions that can be called for
> various actions. You'll probably have to discover some real use cases
> before you'll be able to design the right API for this.

Maybe we should just expose a basic interface to replace the four lines of 
boilerplate (the docstring makes this look more complicated than it really is!):

   WRAPPER_ASSIGNMENTS = ('__module__', '__name__', '__doc__')
   WRAPPER_UPDATES = ('__dict__')
   def update_wrapper(wrapper, wrapped,
                      assigned = WRAPPER_ASSIGNMENTS,
                      updated = WRAPPER_UPDATES):
       """Update a wrapper function to look like the wrapped function

          Attributes of the wrapped function named in the assigned
          argument are assigned directly to the corresponding attributes
          of the wrapper function.
          The update() method of wrapper function attributes named in the
          updated argument are called with the corresponding attribute of
          the wrapped function as their sole argument.
       """
       for attr in assigned:
           setattr(wrapper, attr, getattr(wrapped, attr))
       for attr in updated:
           getattr(wrapper, attr).update(getattr(wrapped, attr))


The two global constants provide clear documentation of the default behaviour 
and the keyword arguments make it easy to copy or update a couple of extra 
arguments if you need to, or to prevent the standard copying.

Including the return statement allows this to be used as a decorator if you 
prefer:

from functools import partial, update_wrapper

@partial(update_wrapper, func)
def wrapper(*args, **kwds):
     # wrap func here.

Cheers,
Nick.



-- 
Nick Coghlan   |   ncoghlan at gmail.com   |   Brisbane, Australia
---------------------------------------------------------------
             http://www.boredomandlaziness.org


More information about the Python-Dev mailing list