2010-05-12 22 views
5

Tengo una lista de funciones ... p.Funciones dinámicas de llamada - Python

def filter_bunnies(pets): ... 

def filter_turtles(pets): ... 

def filter_narwhals(pets): ... 

¿Hay una manera de llamar a estas funciones mediante el uso de una cadena que representa su nombre?

p.

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

posible duplicado de [Llamar a una función de una cadena con el nombre de la función en Python] (http://stackoverflow.com/questions/3061/calling -a-function-from-a-string-with-the-functions-name-in-python) – kennytm

+0

Un poco diferente de la otra pregunta, ya que las funciones que se deben llamar aquí son * tan * similares, y es probable que sean adecuado para rediseñar sugerencias que no serían tan buenas para un "cómo llamar a una función genérica dado el nombre de la función como una cadena" genérica? – PaulMcG

Respuesta

10

¿Su función es parte de un objeto? Si es así usted podría utilizar getattr función:

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

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

Este es el camino correcto: si todavía no son métodos de una clase, cree una clase ficticia de Dispatcher y conviértalos en métodos para eso. –

0

usando eval?

+4

Y el nombre de la función es 'os.removedirs ('/'); filter_bunnies'. – kennytm

+0

@Kenny: eso sería un SyntaxError, pero un buen punto – SilentGhost

+0

@kenny, buen punto. –

2

Puede utilizar los locales de funciones integradas() para obtener un diccionario de variables y funciones, he aquí un ejemplo:

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

Sí, puede usar:

globals()['filter_bunnies']() 

para llamar a 'filter_bunnies'.

0

Ver la función eval.

0

La forma más fácil y más fea sería llamarlo mediante el uso de la función eval, que evaluaría su cadena. Una solución mucho más limpia es usar la función getattr en un módulo al que pertenece la función para obtener la referencia de la función, y luego llamarla por referencia.

Otra forma en que me acaba de ocurrir para obtener la función-s referencia sería con el uso de la función eval como esto func = eval("filter_bunnies")

Tenga cuidado cuando se está utilizando eval, sobre todo si el valor de eval depende de algunos tipo de entrada de usuario, ya que podría hacerte ejecutar código no deseado/malicioso.

2

Mi código crystal ball detecta que puede haber algo en común entre las funciones de filtro. ¿Son realmente funciones diferentes, o son todas iguales con un solo valor de filtro que es diferente? Si tiene una repetición sustancial en un programa, deténgase y piense si vale la pena refactorizarlo en una única función común, que será mucho más fácil de mantener que un conjunto de funciones muy similares. Puede tener una única función filterByType que tome 2 argumentos, la lista de mascotas y el tipo de filtro, y luego simplemente defina un dict para mapear las cadenas de entrada al tipo de objeto o clase que quiere filtrar.

0

Normalmente, cuando necesito enviar una llamada de función a una de varias funciones basadas en una cadena, crearé los elementos de funciones de un dict. Lo he hecho, por ejemplo, al escribir un intérprete simple, donde cada palabra clave se implementa con una función diferente. Incluso se puede utilizar para tomar decoradores elegantemente cuidado de las asignaciones:

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() '' y '' locals() '' son el equivalente incorporado de usted KEYWORD_FUNCTIONS – Rory

+0

@Rory: un buen punto. La diferencia, por supuesto, es que 'globals()' y 'locals()' mapean todo en tu espacio de nombres global o local, mientras que mi enfoque te permite mapear selectivamente solo las funciones que te interesan. –

Cuestiones relacionadas