decorator to replace repetitive object orientated code?
Question: I'm developing a GUI with Qt/PySide with lots of separate classes handling
various widgets. Each widget manages signals between buttons and other user
inputs. I found myself having to reuse code to block widget signals at the
start of method functions and then freeing up the signal at the end. I decided
to try and write a general decorator to do this for me.

I've searched through SO and tried to implement this the best I could with
very little experience using decorators and so I'm not satisfied by my
solution.

**My question is, what is the best way to write a general decorator that can
access and run methods within that class which follow a clear format? Is my
method in anyway a good way?**

For clarity, here's what my code looks like with the repetitive code (I've
removed some for brevity):

    
    
    class WidgetController(...):
    
        def __init__(...):
           self.widget.myWidget.currentIndexChanged.connect(reactToChange)
    
        def reactToChange(...):
            self.widget.myWidget.blockSignals(True) # Repetetive line...
            ...
            self.widget.myWidget.blockSignals(False)
    
        def anotherFunction(...):
            self.widget.anotherWidget.blockSignals(True)
            ...
            self.widget.anotherWidget.blockSignals(False)
    

I would like something like the following:

    
    
    class WidgetController(...):
    
       @blockSignals(myWidget)
       def reactToChange(...):
          ...
    
       @blockSignals(anotherWidget, alsoBlockThisWidget)
       def anotherFunction(...):
          ...
    

I have developed a decorator (with help from
[here](http://www.artima.com/weblogs/viewpost.jsp?thread=240845),
[here](http://stackoverflow.com/questions/4484872/in-python-why-doesnt-exec-
work-in-a-function-with-a-subfunction) and
[here](http://stackoverflow.com/questions/7590682/access-self-from-decorator))
but I hesitate to show it as it feels horribly clunky. It uses `self` where I
don't understand it as well as `exec` in nested functions and needs widget
names to be passed as strings, but it does seem to work. Here it is:

    
    
    class BlockSignals(object):
    
        def __init__(self, *toBeBlocked):
            self.toBeBlocked = toBeBlocked
    
        def __call__(self, f):
            toBeBlocked = self.toBeBlocked
            def wrapped_f(self, *args):
                for b in toBeBlocked:
                    exec 'self.widget.' + b + '.blockSignals(False)' in locals()
                f(self, *args)
                for b in toBeBlocked:
                    exec 'self.widget.' + b + '.blockSignals(False)' in locals()
            return wrapped_f
    

Usage:

    
    
    class WidgetController(...):
    
       @BlockSignals("myWidget")
       def reactToChange(...):
          ...
    
       @BlockSignals("anotherWidget", "alsoBlockThisWidget")
       def anotherFunction(...):
    

As you can see, it's not pretty. I'd love to be able to get rid of the string
parsing, get rid of the `exec`s, sort out the confusing `self`s and be able to
implement it by passing it the actual widget object
`@BlockSignals(self.widget.myWidget)`. Unfortunately I've reached the limit of
my ability, is anyone able to help?


Answer: You are looking for
[getattr](http://docs.python.org/2/library/functions.html#getattr):

    
    
    import functools
    
    def blockSignals(*widgetnames):
        def decorator(func):
            @functool.wraps(func)
            def method(self, *args, **kwargs):
                widgets = [getattr(self.widget, name) for name in widgetnames]
                for widget in widgets:
                    widget.blockSignals(True) 
                result = func(self, *args, **kwargs)
                for widget in widgets:
                    widget.blockSignals(False)
                return result
            return method
        return decorator
    
    class WidgetController(...):
    
        def __init__(...):
           self.widget.myWidget.currentIndexChanged.connect(reactToChange)
    
        @blockSignals('myWidget')
        def reactToChange(...):
            ...
    
        @blockSignals('anotherWidget', 'alsoBlockThisWidget')
        def anotherFunction(...):
            ...
    

You have to pass the _name_ of the widget, not the widget itself, because the
methods are defined at the time the _class_ is defined, not when the
_instance_ is instantiated. The instance `self` and the actual widgets in
`self.widget` do not exist at class-definition time.

The
[functools.wraps](http://docs.python.org/2/library/functools.html#functools.wraps)
decorator copies the name of the original function and its docstring to the
decorated function.

