2012-04-29 2 views
10

Je souhaite attribuer dynamiquement une implémentation de fonction.Affectation dynamique de l'implémentation de la fonction en Python

Commençons par les éléments suivants:

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" 

Dans d'autres langues nous ferait doItBetter une fonction anonyme et l'affecter à l'objet. Mais pas de support pour les fonctions anonymes en Python. Au lieu de cela, nous allons essayer de faire une instance de classe appelables et assignons à la classe:

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() 

Cela me donne ceci:

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'

Enfin, j'ai essayé attribuer le appelable à l'instance d'objet comme un attribut et de l'appeler:

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() 

Cela ne fonctionne aussi longtemps que je ne fait pas référence à soi dans DoItBetter, mais quand je le fais me donne une erreur de nom self.name parce qu'il est le référencement le self du callable, pas la classe propriétaire self. Donc je cherche un moyen pythonien pour assigner une fonction anonyme à une fonction de classe ou une méthode d'instance, où l'appel de méthode peut référencer self de l'objet.

+0

Rien de mal avec la toute première approche que vous avez rejetée. Pourquoi le rendez-vous si complexe? –

+2

Votre erreur est vraiment étrange - essayez-vous d'exécuter un script Python avec un interpréteur ruby? (Votre fichier s'appelle 'prog.rb',' .py' est l'extension de fichier Python). L'erreur n'est certainement pas de Python - 'self' n'est pas un mot-clé dans Python. –

+0

Mon erreur - l'a couru sur un codepad en ligne avec les paramètres ruby ​​- fixe – Yarin

Répondre

23

Votre première approche était OK, il vous suffit d'assigner la fonction à la classe:

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 

Les fonctions anonymes ont rien à voir avec ce (en passant, Python prend en charge des fonctions simples anonymes comprenant des expressions simples voir lambda).

+0

+1 être anonyme n'a pas d'importance ici - tout ce qui compte est que vous pouvez attribuer un fonction. –

+0

Merci cela fonctionne très bien-je ne sais pas pourquoi je pensais que ce n'était pas – Yarin

19

La réponse de yak fonctionne très bien si vous voulez changer quelque chose pour chaque instance d'une classe.

Si vous voulez changer la seule méthode pour une instance particulière de l'objet, et non pour toute la classe, vous aurez besoin d'utiliser le constructeur de type MethodType pour créer une méthode liée:

from types import MethodType 

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

@ Amber- Merci pour cela – Yarin

+1

Au moins en Python 3, il devrait être 'doer.doSomething = MethodType (doItBetter, doer)'. Une bonne explication des différents cas pour les méthodes et les fonctions est donnée dans http://stackoverflow.com/questions/972/adding-a-method-to-an-existing-object-instance – yanlend

+0

@yanlend cette question a été posée Python 2. – Amber

Questions connexes