2012-04-29 18 views
10

Quiero asignar dinámicamente una implementación de funciones.Asignación dinámica de funciones en Python

Vamos a empezar con lo siguiente:

class Doer(object): 

    def __init__(self): 
     self.name = "Bob" 

    def doSomething(self): 
     print "%s got it done" % self.name 

def doItBetter(self): 
    print "Done better" 

En otros idiomas que haría doItBetter una función anónima y asignarlo al objeto. Pero no hay soporte para funciones anónimas en Python. En su lugar, vamos a tratar de hacer una instancia de clase exigible, y asignamos que a la clase:

class Doer(object): 

    def __init__(self): 
     self.name = "Bob" 

class DoItBetter(object): 

    def __call__(self): 
     print "%s got it done better" % self.name 

Doer.doSomething = DoItBetter() 
doer = Doer() 
doer.doSomething() 

que me da esto:

Traceback (most recent call last): Line 13, in doer.doSomething() Line 9, in call print "%s got it done better" % self.name AttributeError: 'DoItBetter' object has no attribute 'name'

Por último, he intentado asignar el exigible a la instancia del objeto como un atributo y llamándolo:

class Doer(object): 

    def __init__(self): 
     self.name = "Bob" 

class DoItBetter(object): 

    def __call__(self): 
     print "%s got it done better" % self.name 


doer = Doer() 
doer.doSomething = DoItBetter() 
doer.doSomething() 

Esto funciona siempre y cuando no autorreferencia en DoItBetter, pero cuando lo hago me da un error en el nombre de self.name porque se hace referencia a el llamable self, no pertenece a la clase self.

Así que estoy buscando una manera pitónica para asignar una función anónima a una función de clase o método de instancia, donde la llamada al método puede hacer referencia al objeto self.

+0

Nada malo con el primer enfoque que rechazaste. ¿Por qué lo haces tan complejo? –

+2

Su error es realmente extraño: ¿está tratando de ejecutar un script de Python con un intérprete de Ruby? (Su archivo se llama 'prog.rb',' .py' es la extensión de archivo de Python). El error definitivamente no es de Python: 'self' no es una palabra clave en Python. –

+0

Mi error: lo ejecuté en una pantalla de códigos en línea con configuración de ruby, se corrigió – Yarin

Respuesta

23

Su primer enfoque estaba bien, sólo hay que asignar la función a la clase:

class Doer(object): 
    def __init__(self): 
     self.name = "Bob" 

    def doSomething(self): 
     print "%s got it done" % self.name 

def doItBetter(self): 
    print "%s got it done better" % self.name 

Doer.doSomething = doItBetter 

funciones anónimas no tienen nada que ver con esto (por cierto, Python soporta funciones anónimas simples que consisten en expresiones individuales , ver lambda).

+0

+1 ser anónimo no importa aquí; todo lo que importa es que puedes asignarle un función. –

+0

Gracias esto funciona bien, no estoy seguro de por qué pensé que no era – Yarin

19

La respuesta de yak funciona muy bien si quiere cambiar algo para cada instancia de una clase.

Si desea cambiar el método sólo para una determinada instancia del objeto, y no para toda la clase, que había necesidad de utilizar el tipo MethodType constructor para crear un método vinculado:

from types import MethodType 

doer.doSomething = MethodType(doItBetter, doer, Doer) 
+0

@ Ámbar- Gracias por esto – Yarin

+1

Al menos en Python 3, debería ser 'doer.doSomething = MethodType (doItBetter, doer)'. Se proporciona una buena explicación de los diferentes casos para métodos y funciones en http://stackoverflow.com/questions/972/adding-a-method-to-an-existing-object-instance – yanlend

+0

@yanlend se solicitó esta pregunta Python 2. – Amber

Cuestiones relacionadas