How do I write a function that adds a method to a class? I have:
class A:
def method(self):
def add_member(name):
self.new_method = def name...?
add_member("f1")
add_member("f2")
In order to answer what I’m trying to do. I’m trying to factor out some pyqt slots. I want to be able to call a function create_slider that will create a QSlider and a QLabel and create the slider handling code, and make the slider-handler update the text in the QLabel. Here’s the slot that needs to be factored out:
def on_sample_slider(self, value):
self.samples = pow(4, value)
self.sample_label.setText('%d' % self.samples)
here’s a method that generates some UI, but it would be nice to also have it generate the on_sample_slider method every time it is called:
def insert_labeled_slider(hbox, name, slider_target):
# name
hbox.addWidget(QLabel(name))
# label
label = QLabel()
label.setMinimumSize(40, 0)
hbox.addWidget(self.sample_label)
#slider
slider = QSlider(Qt.Horizontal)
slider.setRange(0, 6)
slider.setTracking(True)
slider.setPageStep(1)
hbox.addWidget(slider)
self.connect(self.sample_slider, SIGNAL('valueChanged(int)'),
self.on_sample_slider)
self.sample_slider.setValue(0)
return (label, slider)
Final code:
def attach_on_slider(obj, name, variable, label, base):
def on_slider(self, value):
variable = base**value
label.setText('%d' % variable)
# This next line creates a method from the function
# The first arg is the function and the second arg is the object
# upon which you want it to be a method.
method = types.MethodType(on_slider, obj)
obj.__dict__["on_slider_" + name] = method
return method
class A:
def insert_labeled_slider(hbox, name, label_name, variable):
# name
hbox.addWidget(QLabel(label_name))
# label
label = QLabel()
label.setMinimumSize(40, 0)
hbox.addWidget(label)
#slider
slider = QSlider(Qt.Horizontal)
slider.setRange(0, 6)
slider.setTracking(True)
slider.setPageStep(1)
hbox.addWidget(slider)
on_slider_method = attach_on_slider(self, name, variable, label, 4)
self.connect(slider, SIGNAL('valueChanged(int)'),
on_slider_method)
slider.setValue(0)
return (label, slider)
Here’s an real example from your newly posted code:
You can now call it like
original post
Since you say the the member functions are identical, I would do it something like this
Strictly speaking, passing in the name and setting the
__name__attribute on the new function isn’t necessary but it can help with debugging. It’s a little bit of duplication and can pay for itself. If you are going to skip that though, you might as well doThis creates identical methods. Calling either of them will yield the same method.
The first form is more powerful because you can pass other arguments besides the name into
make_methodand have the different versions of the returned method access those parameters in closure so they work differently. Here’s a stupid example with functions (works the same with methods):Here, they’re all essentially the same function but do slightly different things because they have access to the value of
filenamethat they were created with. Closures are definitely something to look into if you’re going to be doing a lot of this sort of thing.There can be a lot more to this so if you have particular questions that this doesn’t address, you should update your question.