What is Python Decorators?

Study group dedicated to learning how to code in the Python language.

Moderators: snarkout, Patrick, dann

Post Reply
User avatar
Jza
Posts: 466
Joined: Sun Oct 30, 2005 7:01 pm
Location: Mexico
Contact:

What is Python Decorators?

Post by Jza » Fri May 04, 2007 4:58 pm

Decorators have something in common with previous metaprogramming abstractions introduced to Python: they do not actually do anything you could not do without them. As Michele Simionato and I pointed out in earlier Charming Python installments, it was possible even in Python 1.5 to manipulate Python class creation without the "metaclass" hook.

http://www-128.ibm.com/developerworks/l ... decor.html

Why use decorators?

The usual method for transforming functions and methods (for instance, declaring them as a class or static method) is awkward and can lead to code that is difficult to understand. Ideally, these transformations should be made at the same point in the code where the declaration itself is made.

The winning syntax as of now uses the '@' symbol, as described in this message. Mark Russell implemented this version. Here is the message describing the patch he checked in.

There has been a long discussion about the syntax to use for decorators in Python.
Examples
Toggle line numbers

Code: Select all

   1 
   2 @classmethod
   3 def foo (arg1, arg2):
   4     ....
Python Decorator Samples:

Code: Select all

   1 def simple_decorator(decorator):
   2     """This decorator can be used to turn simple functions
   3     into well-behaved decorators, so long as the decorators
   4     are fairly simple. If a decorator expects a function and
   5     returns a function (no descriptors), and if it doesn't
   6     modify function attributes or docstring, then it is
   7     eligible to use this. Simply apply @simple_decorator to
   8     your decorator and it will automatically preserve the
   9     docstring and function attributes of functions to which
  10     it is applied."""
  11     def new_decorator(f):
  12         g = decorator(f)
  13         g.__name__ = f.__name__
  14         g.__doc__ = f.__doc__
  15         g.__dict__.update(f.__dict__)
  16         return g
  17     # Now a few lines needed to make simple_decorator itself
  18     # be a well-behaved decorator.
  19     new_decorator.__name__ = decorator.__name__
  20     new_decorator.__doc__ = decorator.__doc__
  21     new_decorator.__dict__.update(decorator.__dict__)
  22     return new_decorator
  23 
  24 #
  25 # Sample Use:
  26 #
  27 @simple_decorator
  28 def mySimpleLoggingDecorator( func ):
  29     def YOU_WILL_NEVER_SEE_THIS_NAME( *args, **kwargs ):
  30         print 'calling %s' % func.__name__
  31         return func( *args, **kwargs )
  32     return YOU_WILL_NEVER_SEE_THIS_NAME
  33 
  34 @mySimpleLoggingDecorator
  35 def double(x):
  36     "Doubles a number"
  37     return 2*x
  38 
  39 assert double.__name__ == 'double'
  40 assert double.__doc__ == 'Doubles a number'
  41 print double(155)
Alexandro COLORADO

User avatar
Vogateer
Posts: 700
Joined: Thu Nov 17, 2005 11:18 pm
Location: Norman, Oklahoma
Contact:

Post by Vogateer » Fri May 04, 2007 5:40 pm

I remember this first example and found it a bit confusing for my simple mind. I did find a link that explained it in a manner I could understand:
Decorators in Python

The simple explanation that sinks in for me is that a decorator expects to be fed a function and modify it in some way. When you call the function or method, the decorator steps in, and it's the decorator that makes the actual call to the function.

The simple example Siddhartha gives is this:

Code: Select all

def decorate(function):
    def _decorate():
        print "Before Calling"
        function()
        print "After Calling"
    return _decorate

@decorate
def mymethod():
    print "Inside Function"
Now we call the function:

Code: Select all

mymethod()
The output:

Code: Select all

Before Calling
Inside Function
After Calling
So you can see how we call "mymethod()" only to have the decorator step in and take over, making its modifications and calling the function from inside the decorator code.

I usually need something this basic to get started, and from there I can start to grasp the concept. I'd check out the link above for some other examples that have helped me understand it a bit better, even though I've never actually used them myself. :lol:
Vim is beautiful

Post Reply