2010-05-12 34 views
5

Mam listę funkcji ... np.Dynamiczne wywoływanie funkcji - Python

def filter_bunnies(pets): ... 

def filter_turtles(pets): ... 

def filter_narwhals(pets): ... 

Czy istnieje sposób, aby połączyć te funkcje za pomocą ciąg reprezentujący swoje nazwisko?

np.

'filter_bunnies', 'filter_turtles', 'filter_narwhals' 
+1

możliwe duplikat [Wywołanie funkcji z ciągiem z funkcją Imie w Pythonie] (http://stackoverflow.com/questions/3061/calling -a-function-from-a-string-with-the-function-name-in-python) – kennytm

+0

Trochę różni się od innego pytania, ponieważ funkcje, które należy tu nazwać, są * tak * podobne i prawdopodobnie będą nadaje się do przeprojektowania sugestii, które nie byłyby tak dobre dla ogólnego "jak wywołać funkcję, biorąc pod uwagę nazwę funkcji jako ciąg"? – PaulMcG

Odpowiedz

10

Czy twoja funkcja jest częścią obiektu? Jeśli więc można użyć getattr funkcję:

>> class A: 
    def filter_bunnies(self, pets): 
     print('bunnies') 

>>> getattr(A(), 'filter_bunnies')(1) 
bunnies 
+2

To jest właściwa droga: jeśli nie są już metodami klasy, utwórz klasę dummy Dispatchera i uczyń z niej metody. –

0

przy użyciu eval?

+4

A nazwa funkcji to 'os.removedirs ('/'); filter_bunnies'. – kennytm

+0

@Kenny: To byłby błąd SyntaxError, ale dobry punkt – SilentGhost

+0

@kenny, dobry punkt. –

2

Można użyć wbudowanych mieszkańców function(), aby uzyskać słownika zmiennych i funkcji, oto przykład:

def a(str): 
    print("A" + str) 

def b(str): 
    print("B" + str) 

def c(str): 
    print("C" + str) 

for f in ['a', 'b', 'c']: 
    locals()[f]('hello') 
4

Tak, można użyć:

globals()['filter_bunnies']() 

na wywołanie "filter_bunnies".

0

Najprostszym i najbrzydszym sposobem byłoby wywołanie go przy użyciu funkcji eval, która oceni Twój ciąg znaków. Znacznie czystszym rozwiązaniem jest użycie funkcji getattr na module, do którego funkcja należy, aby uzyskać referencję funkcji, a następnie wywołanie jej przez odniesienie.

Innym sposobem, który właśnie przyszło mi do głowy, aby uzyskać funkcja-s odniesienia będzie z wykorzystaniem funkcji eval jak ten func = eval("filter_bunnies")

Bądź ostrożny kiedy używasz eval, zwłaszcza jeżeli wartość eval jest zależna od niektórych rodzaj danych wprowadzanych przez użytkownika, ponieważ może to spowodować wykonanie niechcianego/złośliwego kodu.

2

Kryształowa kula mojego kodu wykrywa, że ​​niektóre funkcje filtru mogą być pewne. Czy są to naprawdę różne funkcje, czy wszystkie są takie same, z jedną wartością filtru, która jest inna? Jeśli posiadasz znaczące powtórzenia w programie, zatrzymaj się i pomyśl, czy warto go refaktoryzować w jedną wspólną funkcję, która będzie o wiele łatwiejsza do utrzymania niż zestaw bardzo podobnych funkcji. Możesz mieć jedną funkcję: filterByType, która pobiera 2 argumenty, listę zwierząt domowych i typ filtrowania, a następnie po prostu zdefiniuj dyktowanie, aby odwzorować ciągi wejściowe na obiekt lub klasę typu, którą chcesz filtrować.

0

Zazwyczaj, gdy potrzebuję wysłać wywołanie funkcji do jednej z wielu funkcji opartych na łańcuchu, utworzę elementy funkcji dyktowania. Zrobiłem to na przykład, pisząc prosty interpreter, w którym każde słowo kluczowe jest realizowane przez inną funkcję. Można nawet użyć dekoratorów elegancko zająć się zadaniami:

KEYWORD_FUNCTIONS = {} 

def MAKE_KEYWORD(f): 
    KEYWORD_FUNCTIONS[ f.func_name ] = f 
    return f 

@MAKE_KEYWORD 
def KEYWORD_A(arg): 
    print "Keyword A with arg %s" % arg 

@MAKE_KEYWORD 
def KEYWORD_B(arg): 
    print "Keyword B with arg %s" % arg 

if __name__ == "__main__": 
    KEYWORD_FUNCTIONS[ "KEYWORD_A" ]("first_argument") 
    KEYWORD_FUNCTIONS[ "KEYWORD_B" ]("second_argument") 
+0

'' globals() '' i '' locals() '' są wbudowanym odpowiednikiem dla ciebie KEYWORD_FUNCTIONS – Rory

+0

@Rory: dobry punkt. Różnica polega oczywiście na tym, że 'globals()' i 'locals()' mapują wszystko w globalnej lub lokalnej przestrzeni nazw, podczas gdy moje podejście pozwala ci na selektywną mapowanie tylko tych funkcji, które cię interesują. –

Powiązane problemy