2012-07-02 34 views
24

¿Cómo crear dinámicamente una función en Python?Python: crea dinámicamente la función en el tiempo de ejecución

Vi algunas respuestas aquí, pero no pude encontrar una que describa el caso más general.

considerar:

def a(x): 
    return x + 1 

Cómo crear dicha función en la marcha? ¿Tengo que compile('...', 'name', 'exec')? ¿Pero entonces qué? ¿Creando una función ficticia y reemplazando su objeto de código por uno del paso de compilación?

¿O debería usar types.FunctionType? ¿Cómo?

me gustaría personalizar todo: número de argumentos, su contenido, el código en el cuerpo de la función, el resultado, ...

+3

posible duplicado de [funciones dinámicas y anónimas verdaderos posibles en Python?] (Http://stackoverflow.com/questions/10303248/true-dynamic-and-anonymous-functions-possible-in-python) –

+0

No creo que sea un duplicado: 'dynf = FunctionType (compile ('def f (x): return x + 3', 'dyn.py', 'exec'), globals())' y 'print dynf (1) 'rompe con' TypeError: '() no toma argumentos (se da 1)' ' –

+1

El hecho de que la respuesta sea incorrecta no significa que esta no sea una pregunta duplicada. –

Respuesta

13

Uso exec:

>>> exec("""def a(x): 
... return x+1""") 
>>> a(2) 
3 
9

¿Vio this, su una ejemplo, que le indica cómo utilizar types.FunctionType

ejemplo:

import types 

def create_function(name, args): 
    def y(): pass 

    y_code = types.CodeType(args, 
          y.func_code.co_nlocals, 
          y.func_code.co_stacksize, 
          y.func_code.co_flags, 
          y.func_code.co_code, 
          y.func_code.co_consts, 
          y.func_code.co_names, 
          y.func_code.co_varnames, 
          y.func_code.co_filename, 
          name, 
          y.func_code.co_firstlineno, 
          y.func_code.co_lnotab) 

    return types.FunctionType(y_code, y.func_globals, name) 

myfunc = create_function('myfunc', 3) 

print repr(myfunc) 
print myfunc.func_name 
print myfunc.func_code.co_argcount 

myfunc(1,2,3,4) 
# TypeError: myfunc() takes exactly 3 arguments (4 given) 
+2

Sí, lo vi y parece ser exactamente lo que busco. Pero no sé cómo crear/modificar el cuerpo de la función y devolver valores ...? –

+1

Acabo de probarlo, cuando cambias la llamada al final con el nb correcto de args, segfault ... –

2

¿Qué hay de este enfoque?

En este ejemplo estoy parametrización funciones de primer orden en una variable (x -> ax + b) en una clase:

class Fun: 
    def __init__(self, a,b): 
    self.a, self.b = a,b 

    def f(self, x): 
    return (x*self.a + self.b) 

u = Fun(2,3).f 

Aquí u será la función x-> 2x + 3 .

7

Si necesita crear dinámicamente una función de una plantilla determinada tratar esta pieza:

def create_a_function(*args, **kwargs): 

    def function_template(*args, **kwargs): 
     pass 

    return function_template 

my_new_function = create_a_function() 

Dentro de la función create_a_function() se puede controlar, que eligió a la plantilla. La función interna function_template sirve como plantilla. El valor de retorno de la función del creador es una función. Después de la asignación, usa my_new_function como una función normal.

Por lo general, este patrón se utiliza para decoradores de funciones, pero también puede ser práctico aquí.

0

Puede usar lambda para esto.

a=lambda x:x+1 
>>a(2) 
3 
Cuestiones relacionadas