patternpythonMinor
Python subclass method decoration
Viewed 0 times
subclassdecorationpythonmethod
Problem
Is this code Pythonic?
Final decorator code:
def emit_decorator(method, signal_name):
def decorated(self, *args, **kwargs):
retval = method(self, *args, **kwargs)
getattr(self, signal_name).emit()
return retval
return decorated
class Model(base.Transformer, Node):
"""
Transformer subclass that implements the Model of the Model-View-Controller
paradigm.
"""
def __init__(self, *args, **kwargs):
super(Model, self).__init__(*args, **kwargs)
modelChanged = pyqtSignal()
def create_view(self, parent=None):
return View(self, parent)
for x in ('importance_changed',
'evidence_changed',
):
setattr(Model, x,
emit_decorator(getattr(Model, x), 'modelChanged'))Final decorator code:
from functools import update_wrapper
def method_emit_decorator(signal_name):
def method_decorator(method):
def decorated(self, *args, **kwargs):
retval = method(self, *args, **kwargs)
getattr(self, signal_name).emit()
return retval
return update_wrapper(decorated, method)
return method_decorator
def class_emit_decorator(signal_name_to_method_names_dict):
def class_decorator(cls):
retval = cls
for signal_name, method_names in (
signal_name_to_method_names_dict.items()):
for method_name in method_names:
method = method_emit_decorator(signal_name)(
getattr(cls, method_name))
setattr(retval, method_name, method)
return retval
return class_decoratorSolution
Modifying the class after defining it smells. That is, its not necessarily a bad idea but one should explore options before resorting to it.
When "decorating" a function you should use the functools.wraps decorator. It will make the decorated function look more like the original.
The code you are replacing looks like:
Your code is harder to read and longer then just writing those two functions. Its not really worth implementing what you've done just for two functions. However, if you have a lot of functions then the situation changes.
Your emit_decorator function isn't a decorator. Dectorators have to take exactly one argument, (the function they are wrapping) to be used with the @syntax.
When "decorating" a function you should use the functools.wraps decorator. It will make the decorated function look more like the original.
The code you are replacing looks like:
def importance_changed(self):
return_value = super(Model, self).importance_changed()
self.modelChanged.emit()
return return_valueYour code is harder to read and longer then just writing those two functions. Its not really worth implementing what you've done just for two functions. However, if you have a lot of functions then the situation changes.
Your emit_decorator function isn't a decorator. Dectorators have to take exactly one argument, (the function they are wrapping) to be used with the @syntax.
Code Snippets
def importance_changed(self):
return_value = super(Model, self).importance_changed()
self.modelChanged.emit()
return return_valueContext
StackExchange Code Review Q#2890, answer score: 3
Revisions (0)
No revisions yet.