2013-02-24 8 views
5

Python pozwala na przypisanie funkcji predefiniowanego do klasy jako atrybut, takich jakPrzypisywanie funkcji jako atrybutów obiektu, a następnie wywoływanie bez domniemanego "ja" argumentu?

def fish_slap(fish): 
    # do something 

class dance(object): 
    dance_move=fish_slap 

Jednak jeśli spróbujemy mów

d=dance() 
d.dance_move("Halibut") 

otrzymujemy pojawia się następujący błąd

TypeError: fish_slap() takes exactly 1 arguement (2 given) 

Python wydaje się to postrzegać jako metodę obiektową i podać domniemany argument "ja". Wystarczająco uczciwe wydaje się, że właśnie dowiedziałem się, że przypisanie funkcji jako atrybutu w ten sposób jest równoznaczne z definiowaniem funkcji bezpośrednio w klasie. Widzę, że jest to przydatna funkcja.

Jednak w tym przypadku nie jest to, czego chcę. W mojej aplikacji mam modele statystyczne zakodowane jako różne klasy, które również mają swoje własne "pociągowe" metody szkolenia parametrów modelu względem dostarczonych danych. W tym celu należy zastosować funkcję celu, która ma zminimalizować (lub zmaksymalizować) wartość potrzebnych do dostarczenia. Przykładową prostą funkcją celu jest np.

def RMSE(predicted,observed): 
    "Root mean squared error" 
    return sp.sqrt(sp.mean((predicted-observed)**2)) 

gdzie SciPy została zaimportowana jako sp. Te obiektywne funkcje są zdefiniowane w jednym pliku .py i są używane w całym moim kodzie i naturalnie istnieją jako samodzielne funkcje, a nie jako metody klasowe z domniemanym argumentem "ja".

Chcę móc ustawić żądaną funkcję celu jako atrybut tak, że każda późniejsza praca obiekt modelu nie korzysta z tej funkcji, na przykład

some_model=SomeModel(initial_parameter_values_guess) 
some_model.objective_function = RMSE 
some_model.train(training_data) 
predictions_RMSE = some_model.predict() 
some_mode.objective_function = MAE 
predictions_MAE = some_model.predict() 

W tym przykładzie wydaje mogę tylko przekazać Funkcja obiektywna jako argument do treningu, jednak w mojej aplikacji jest o wiele więcej do zrobienia i wydaje się, że bardziej sensownym jest móc ustawić/uzyskać funkcję celu zamiast powtarzać ją jako argument.

Istnieje wiele sposobów obejścia tego podstawowego zachowania, ale jakie jest najbardziej pittonowe podejście?

Należy zauważyć, że mój obecny kod jest zgodny z python2 i python3. Jeśli istnieją rozwiązania specyficzne dla wersji, proszę o wskazanie tego. Używam python2, aby móc używać matplotlib, ale staram się zapewnić, że kod jest zgodny z python3 niezależnie od tego modułu.

+0

dlaczego nie po prostu zmieniasz 'def fish_slap (fish):' na 'def fish_slap (self, fish):'? – Blender

+0

@Blender, patrz akapit po zdefiniowaniu RMSE. Funkcje te są już zdefiniowane i używane w wielu innych miejscach jako samodzielne funkcje bez argumentów "ja". – Bogdanovist

Odpowiedz

8

Można użyć staticmethod

class dance(object): 
    dance_move=staticmethod(fish_slap) 

pamiętać, że nie trzeba używać staticmethod jeśli przypisanie do atrybutu o przykład:

>>> def move(): 
...  print "disco party!" 
... 
>>> class dance(object): 
...  dance_move = staticmethod(move) 
... 
>>> d = dance() 
>>> d.dance_move() 
disco party! 
>>> d.break_it_down = move 
>>> d.break_it_down() 
disco party! 
+0

Idealny. Najwyraźniej nadal jestem pytonem n00b. – Bogdanovist

Powiązane problemy