2009-04-13 23 views
6

Este fue el mejor nombre que pude encontrar para el tema y ninguna de mis búsquedas arrojó información relevante para la pregunta.Llamar a funciones desconocidas de Python

Como llamar una función de una cadena, es decir

functions_to_call = ["func_1", "func_2", "func_3"] 

for f in functions_to_call: 
    call f 
+0

cómo son las funciones desconocidas cuando parece conocer las funciones que desea llamar desde una lista –

+0

Los nombres de las funciones podrían provenir de una fuente externa, como un archivo de texto. – gregturn

+0

Está destinado a ser un sistema semiabstracto para ejecutar juegos (para poder reutilizarlo) y por lo tanto estarán lo suficientemente cerca de un archivo de texto. – Teifion

Respuesta

2
functions_to_call = ["func_1", "func_2", "func_3"] 

for f in functions_to_call: 
    eval(f+'()') 

Editado para añadir:

Sí, eval() por lo general es una mala idea, pero esto es lo el OP estaba buscando.

+0

Esto funciona perfectamente, no estoy seguro de por qué tiene tan pocos votos favorables. – Teifion

+0

-1 por no mencionar que el uso de eval es una mala idea en general. – nosklo

+2

de hecho. No hay ninguna razón para usar eval() aquí; 'locals() [f]()' hubiera estado bien. Esa sigue siendo una forma muy cuestionable de hacerlo, pero mucho mejor que eval(). – bobince

15

¿Cómo se desconoce el nombre de la función a llamar? Almacenar las funciones en lugar del nombre:

functions_to_call = [int, str, float] 

value = 33.5 

for function in functions_to_call: 
    print "calling", function 
    print "result:", function(value) 
+0

Podría explicar todo sobre el programa exacto, pero sentí que sería una pérdida de espacio y distraería del problema específico en cuestión. – Teifion

+0

Las funciones se almacenan como cadenas en la pregunta, pero no en su respuesta, por lo que la respuesta no es correcta ... – sykora

+1

@sykora ... pero muestra una mejor manera si puede cambiar los requisitos de su problema un poco. –

1

Ver las eval and compile funciones.

Esta función también se puede utilizar para ejecutar objetos de código arbitrario (como los creados por compile()). En este caso, pase un objeto de código en lugar de una cadena. Si el objeto de código ha sido compilado con 'exec' como el argumento kind, el valor de retorno de eval() será None.

+0

-1 por no mencionar que el uso de exec/eval es una mala idea en general. – nosklo

8

Algo así ... cuando yo estaba mirando a los punteros de función en Python ..

def myfunc(x): 
    print x 

dict = { 
    "myfunc": myfunc 
} 

dict["myfunc"]("hello") 

func = dict.get("myfunc") 
if callable(func): 
    func(10) 
+0

+1 dicts de envío son una buena forma de hacerlo si realmente necesita tener una cadena – nosklo

+0

"punteros a función"? No tal cosa. –

+0

sí ... lo sé ... estaba buscando algo equivalente ... – LB40

19

Puede utilizar los locales pitón orden interna() para obtener declaraciones locales, por ejemplo:

def f(): 
    print "Hello, world" 

def g(): 
    print "Goodbye, world" 

for fname in ["f", "g"]: 
    fn = locals()[fname] 
    print "Calling %s" % (fname) 
    fn() 

Puede usar el módulo "imp" para cargar funciones de archivos python especificados por el usuario, lo que le da un poco más de flexibilidad.

El uso de los locales() se asegura de que no se puede llamar pitón genérico, mientras que con eval, que podría terminar con el usuario el establecimiento de su cadena a algo malo, como:

f = 'open("/etc/passwd").readlines' 
print eval(f+"()") 

o similar y terminar con tu programación haciendo cosas que no esperas que sean posibles. Usar trucos similares con los locals() y los dicts en general solo le dará a los atacantes KeyErrors.

+0

eres un idiota vicioso nosklo. él * sí * lo explicó bastante bien – mpen

+0

@Mark: de hecho. Comenté la respuesta incorrecta, lo siento. Remoto. – nosklo

1

No utilice eval!Casi nunca es necesario, las funciones en Python son sólo atributos como todo lo demás, y son accesibles, ya sea usando getattr en una clase, o por medio de locals():

>>> print locals() 
{'__builtins__': <module '__builtin__' (built-in)>, 
'__doc__': None, 
'__name__': '__main__', 
'func_1': <function func_1 at 0x74bf0>, 
'func_2': <function func_2 at 0x74c30>, 
'func_3': <function func_3 at 0x74b70>, 
} 

ya que es un diccionario, puede obtener las funciones a través de la dict- llaves func_1, func_2 y func_3:

>>> f1 = locals()['func_1'] 
>>> f1 
<function func_1 at 0x74bf0> 
>>> f1() 
one 

Por lo tanto, la solución sin recurrir a eval:

>>> def func_1(): 
...  print "one" 
... 
>>> def func_2(): 
...  print "two" 
... 
>>> def func_3(): 
...  print "three" 
... 
>>> functions_to_call = ["func_1", "func_2", "func_3"] 
>>> for fname in functions_to_call: 
...  cur_func = locals()[fname] 
...  cur_func() 
... 
one 
two 
three 
Cuestiones relacionadas