2010-11-20 9 views
6

¿Cómo escribo una función que agrega un método a una clase? Tengo:Metaprogramación de Python: genera automáticamente funciones de miembro

class A: 
    def method(self): 
     def add_member(name): 
      self.new_method = def name...? 

     add_member("f1") 
     add_member("f2") 

Con el fin de responder a lo que estoy tratando de hacer. Estoy tratando de factorizar algunas ranuras pyqt. Deseo poder llamar a una función create_slider que creará un QSlider y un QLabel y creará el código de control del control deslizante, y hará que el control deslizante actualice el texto en el QLabel. Aquí está la ranura que debe tenerse en cuenta a cabo:

def on_sample_slider(self, value): 
     self.samples = pow(4, value) 
     self.sample_label.setText('%d' % self.samples) 

aquí es un método que genera un poco de interfaz de usuario, pero sería bueno que también lo han de generar el método on_sample_slider cada vez que se llama:

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) 

código final:

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) 
+1

son la f1' métodos 'y' f2' ya definido en alguna parte? – BudgieInWA

+0

no, estoy tratando de generarlos dentro de la función auxiliar. –

+0

(Estoy tratando de factorizar algunas funciones de miembro idénticas.) –

Respuesta

7

He aquí un ejemplo real de su código recién publicado:

import types 

def attach_on_sample_slider(obj, base): 
    def on_sample_slider(self, value): 
     self.samples = base**value 
     self.sample_label.setText('%d' % self.samples) 

    # 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. 
    obj.on_sample_slider = types.MethodType(on_sample_slider, obj) 

Ahora puede llamar así

def some_method(self, foo): 
    attach_on_sample_slider(self, 4) 

post original

Dado que usted dice las las funciones miembro son idénticos, lo haría algo como esto

def make_method(name): 
    def method(self, whatever, args, go, here): 
     #whatever code goes here 
    method.__name__ = name 
    return method 


class A(object): 
    method1 = make_method('method1') 
    method2 = make_method('method2') 

Estrictamente hablando, pasando el nombre y configurando elEl atributoen la nueva función no es necesario pero puede ayudar con la depuración. Es un poco duplicado y puede pagarse solo. Sin embargo, si va a saltear eso, también puede hacerlo

class A(object): 
    def method1(self, arg1, arg2): 
     #code goes here 

    method2 = method1 
    method3 = method1 

Esto crea métodos idénticos. Llamar a cualquiera de ellos producirá el mismo método.

La primera forma es más poderosa porque puede pasar otros argumentos además del nombre en make_method y tener las diferentes versiones del método devuelto acceder a esos parámetros en el cierre para que funcionen de manera diferente. He aquí un ejemplo tonto con funciones (funciona de la misma con métodos):

def make_opener(filename): 
    def opener(): 
     return open(filename) 
    return opener 

open_config = make_opener('config.cfg') 
open_log = make_opener('log.log') 

aquí, todos son esencialmente la misma función, pero hacer las cosas un poco diferentes porque tienen acceso al valor de filename que fueron creados con . Los cierres son definitivamente algo a investigar si vas a hacer mucho de este tipo de cosas.

No puede haber mucho más que esto por lo que si usted tiene preguntas particulares que esto no aborda, debe actualizar su pregunta.

+0

Esto es totalmente sorprendente, y una de las razones por las que estoy usando python en lugar de C++. –

+0

Noté que estás haciendo los métodos en el alcance principal de la clase. ¿Pueden los métodos hacerse en una función miembro de la clase y luego enlazarse en ese momento? Por ejemplo, escribiendo 'self.method1 = make_method ...'? –

+0

¡Guau, no sabía que podía hacer eso con Python! – helpermethod

Cuestiones relacionadas