2012-04-29 14 views
10

Chcę dynamicznie przypisać implementację funkcji.Dynamiczne przypisywanie implementacji funkcji w języku Python

Zacznijmy następujące:

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" 

W innych językach chcielibyśmy zrobić doItBetter anonimową funkcję i przypisać go do obiektu. Ale brak obsługi anonimowych funkcji w Pythonie. Zamiast tego spróbujemy dokonywania wpłacone instancję klasy i przypisać, że do klasy:

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

który daje mi to:

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'

Wreszcie, próbowałem przypisywania wpłacone do instancji obiektu jako atrybut i nazywając go:

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

to działa tak długo, jak nie odwoływać siebie w DoItBetter, ale kiedy robię daje mi błąd nazwy na self.name bo to odwołanie the callable to self, nie posiadająca klasy self.

Poszukuję więc pytonowego sposobu przypisania anonimowej funkcji do funkcji klasy lub metody instancji, gdzie wywołanie metody może odwoływać się do obiektu self.

+0

Nic złego w pierwszym podejściu, które odrzuciłeś. Dlaczego czynisz to tak skomplikowanym? –

+2

Twój błąd jest naprawdę nieparzysty - czy próbujesz uruchomić skrypt Pythona z interpreterem ruby? (Twój plik nazywa się 'prog.rb',' .py' jest rozszerzeniem pliku Python). Błąd zdecydowanie nie pochodzi z języka Python - 'self' nie jest słowem kluczowym w Pythonie. –

+0

Mój błąd - uruchomiłem go na internetowym padzie kodowym z ustawieniami ruby ​​- naprawiono – Yarin

Odpowiedz

23

Twoje pierwsze podejście było OK, po prostu trzeba przypisać funkcję do klasy:

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 

anonimowych funkcje mają nic wspólnego z tym (nawiasem mówiąc, Python obsługuje proste funkcje anonimowe, składające się z pojedynczych wyrażeń , patrz lambda).

+0

+1 anonimowy nie ma tutaj znaczenia - ważne jest tylko przypisanie funkcjonować. –

+0

Dzięki temu działa świetnie - nie jestem pewien, dlaczego myślałem, że to nie jest – Yarin

19

Odpowiedź jaka działa świetnie, jeśli chcesz coś zmienić dla każdej instancji klasy.

Jeśli chcesz zmienić metodę tylko do określonego przykład obiektu, a nie dla całej klasy, trzeba by użyć konstruktora MethodType typu stworzyć związanego metody:

from types import MethodType 

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

@ Amber- Dziękuję za to – Yarin

+1

Przynajmniej w Pythonie 3, powinno to być 'doer.doSomething = MethodType (doItBetter, doer)'. Dobre wyjaśnienie różnych przypadków dla metod i funkcji znajduje się w http://stackoverflow.com/questions/972/adding-a-method-to-an-existing-object-instance – yanlend

+0

@yanlend pytanie to zostało zadane Python 2. – Amber

Powiązane problemy