views:

1636

answers:

8

Have you got a python decorator that you really love? Post it here!

Here is my favorite, although since I have not known about the feature very long, it may change soon...

def debug(f):
    """
    Decorator.
    Function will enable debugging just for itself.
    Won't change anything if debugging is already enabled.
    """
    def decorator(*args,**kargs):
        prevState = options['debug']
        options['debug'] = True
        f(*args,**kargs)
        options['debug'] = prevState
    decorator.__name__ = f.__name__
    return decorator
+3  A: 

I wrote this one some time ago to execute wxPython UI methods from within a thread (this is only possible in the main thread normally)

def ui_thread(func):
    """
    a decorator that calls the target in the UI thread's context
    via wx.CallAfter(),
    asynchronously, not waiting for function to complete
    """
    def f(*args, **kwargs):
        wx.CallAfter(target, *args, **kwargs)

    return f

It uses the wx.CallAfter() method to post a function to the main thread. The decorator nicely wraps any method or function so you do not need to worry about thread switching or messages.

A simple example:

@ui_thread
def _message_box(self, msg, icon):
    wx.MessageBox(
        message=self._wrapped_msg(msg),
        caption=self.tool.description,
        style=wx.OK | wx.CENTRE | icon,
    )

This can easily be extended to wait for the call to execute and receive back results.

Ber
+1  A: 

I discovered a decorator for making properties easier and I use it a lot:

def propertx(fct):
    arg = [None, None, None, None]
    for i, f in enumerate(fct()):
        arg[i] = f
    if not arg[3]:
        arg[3] = fct.__doc__

    return property(*arg)

class MyClass(object):

    def __init__(self, lines):
        self.lines = lines

    @propertx
    def content():
        def get(self):
            return '\n'.join(self.lines)
        def set(self, text):
            self.lines = text.split('\n')
        return (get, set)
Oli
+9  A: 

I like the new capability to use a property as a decorator in python2.6 and later. You could always use it to define a getter for read-only properties:

@property
def fullname(self):
    return "%s %s" % (self.forename, self.surname)

But now you can also use it to easily define setters and deleters:

@property
def fullname(self):
    return "%s %s" % (self.forename, self.surname)

@fullname.setter
def fullname(self, value):
    self.forename, self.surname = value.split(" ",1)
Brian
+3  A: 

If you use the Twisted library, the inlineCallbacks decorator is the best thing ever. It allows you to turn complicated series of asynchronous callbacks into what appears to be a single synchronous function (much easier to understand and maintain).

The function itself is a generator, and the decorator automatically sets up next() as the callback for each result.

DNS
+1  A: 
def transactional(fn):
    def wrapper(*args, **kwargs):
        Session.begin()
        try:
            ret = fn(*args, **kwargs)
            Session.commit()
            return ret
        except:
            Session.rollback()
            raise
    return wrapper
Adam Dziendziel
+4  A: 

The Django framework provides several kinds of decorators to define transactional and caching behavior for views.

Ber
Seconded. I love the way Django makes use of decorators to make things look a lot more natural.
sykora
+13  A: 

@memoize is great.

@memoize
def Fib(n):
    if n <= 1:
       return 1
    else:
       return Fib(n-1) + Fib(n-2)

The function values are memoized and Fib just has O(n) instead of exponential complexity. There are several implementations, just google it or follow the links in the wiki article.

Dario
A: 

Here is a good one. This converts function that operates on a tuple to a function that operates on list of tuples.

class onlist(object):

    def __init__(self,f):
     self.f = f
    def __call__(self,args_list):
     def wrapped_f(args_list):
      return [self.f(*args) for args in args_list]
     return wrapped_f(args_list)

if __name__=='__main__':


    @onlist
    def f(a,b,c):
     return a+b+c

    a = range(5)
    b = range(5)
    c = range(5)
    data = list(zip(a,b,c))
    print(f(data))
TheMachineCharmer
how about making them runs in parallel (threaded)
Lie Ryan
:) Cool! You are right. In my final year B.Tech. project I developed a distributed computing application similar to map-reduce. And this decorator was the best part of it. Thanks!
TheMachineCharmer