programacion poo polimorfismo otra orientada objetos metodos metodo llamar herencia clases clase python python-2.7 closures metaprogramming dynamic-function

poo - Creación de funciones dinámicas de Python con nombres personalizados



poo python 3 (5)

Es posible que desee utilizar eval ; construirá la cadena que contiene la definición de Python de cada función (es decir, una cadena de def func1 comienza con def func1 ...) y luego la eval .

Pero generaría un nombre único para cada función (p. Ej. genfun345 ). No use alguna entrada de usuario sin marcar para tales nombres. Porque si el nombre es el mismo que el de un nombre conocido en Python, se enfrentará a un desastre difícil de depurar.

¿Confías en las entradas a partir de las cuales se realizan estas funciones? ¿Te importa el malware o el abuso?

Lea sobre las macros de Hygenic en wikipedia.

Disculpas si esta pregunta ya ha sido planteada y respondida. Lo que tengo que hacer es muy simple en concepto, pero desafortunadamente no he podido encontrar una respuesta en línea.

Necesito crear funciones dinámicas en Python (Python2.7) con nombres personalizados en tiempo de ejecución. El cuerpo de cada función también debe construirse en tiempo de ejecución, pero es (casi) lo mismo para todas las funciones.

Comienzo con una lista de nombres.

func_names = ["func1", "func2", "func3"]

Tenga en cuenta que la lista nombre_func puede contener una lista de nombres arbitrarios, por lo que los nombres NO serán simplemente func1, func2, func3, ....

Quiero que el resultado sea:

def func1(*args): ... def func2(*args): ... def func3(*args): ...

La razón por la que necesito hacer esto es que cada nombre de función corresponde a un caso de prueba que luego se llama desde el mundo exterior.

actualización : no hay entrada de usuario. Estoy atando dos extremos de un módulo mucho más grande. Un extremo determina cuáles son los casos de prueba y, entre otras cosas, completa una lista de los nombres de los casos de prueba. El otro extremo son las funciones mismas, que deben tener un mapeo 1: 1 con el nombre del caso de prueba. Así que tengo el nombre de los casos de prueba, sé lo que quiero hacer con cada caso de prueba, solo necesito crear las funciones que tienen el nombre de los casos de prueba. Como el nombre de los casos de prueba se determina en el tiempo de ejecución, la creación de la función basada en esos casos de prueba también debe estar en tiempo de ejecución.

actualización : también puedo ajustar estas funciones nombradas personalizadas en una clase si eso facilita las cosas.

Puedo codificar el contenido de las funciones (ya que son casi las mismas) en una cadena, o puedo basarlo en una clase base previamente definida. Solo necesito saber cómo poblar las funciones con este contenido.

Por ejemplo:

func_content = """ for arg in args: print arg """

Gracias por adelantado,

Mahdi


Extendiendo la respuesta de Shane ya que acabo de encontrar esta pregunta cuando busco una solución a un problema similar. Tenga cuidado con el alcance de las variables. Puede evitar problemas de alcance utilizando una función de generador para definir el alcance. Aquí hay un ejemplo que define los métodos en una clase:

class A(object): pass def make_method(name): def _method(self): print("method {0} in {1}".format(name, self)) return _method for name in (''one'', ''two'', ''three''): _method = make_method(name) setattr(A, name, _method)

En uso:

In [4]: o = A() In [5]: o.one() method one in <__main__.A object at 0x1c0ac90> In [6]: o1 = A() In [7]: o1.one() method one in <__main__.A object at 0x1c0ad10> In [8]: o.two() method two in <__main__.A object at 0x1c0ac90> In [9]: o1.two() method two in <__main__.A object at 0x1c0ad10>


Por lo que describes, no creo que necesites descender a eval o macros, crear instancias de función por cierre debería funcionar bien. Ejemplo:

def bindFunction1(name): def func1(*args): for arg in args: print arg return 42 # ... func1.__name__ = name return func1 def bindFunction2(name): def func2(*args): for arg in args: print arg return 2142 # ... func2.__name__ = name return func2

Sin embargo, es probable que desee agregar esas funciones por nombre a algún ámbito para que pueda acceder a ellas por su nombre.

>>> print bindFunction1(''neat'') <function neat at 0x00000000629099E8> >>> print bindFunction2(''keen'') <function keen at 0x0000000072C93DD8>


Probablemente hay una especie de introspección para hacer este tipo de cosas, pero no creo que sea el enfoque pitónico del problema.

Creo que deberías aprovechar la naturaleza de las funciones en python como ciudadanos de primer nivel. Use cierres como señaló Shane Holloway, para personalizar los contenidos de la función como desee. Luego, para el enlace de nombre dinámico, use un diccionario cuyas claves sean los nombres definidos dinámicamente, y los valores serán las funciones en sí.

def function_builder(args): def function(more_args): #do stuff based on the values of args return function my_dynamic_functions = {} my_dynamic_functions[dynamic_name] = function_builder(some_dynamic_args) #then use it somewhere else my_dynamic_functions[dynamic_name](the_args)

Espero que tenga sentido su caso de uso.


Si entiendo tus requisitos correctamente, parece que quieres asignar dinámicamente funciones nuevas a nombres existentes o alternativos, en cuyo caso algo de las siguientes líneas debería hacer el trabajo:

import sys testcases = [] def testcase(f): """ testcase function decorator """ testcases.append(f) return f @testcase def testcase0(*args): print ''testcase0 called, args:'', args @testcase def testcase1(*args): print ''testcase1 called, args:'', args @testcase def testcase2(*args): print ''testcase2 called, args:'', args def assign_function_names(func_names, namespace=None): if namespace is None: namespace = sys._getframe(1).f_globals # default to caller''s globals for name, func in zip(func_names, testcases): func.__name__ = name # optional namespace[name] = func assign_function_names(["funcA", "funcB", "funcC"]) funcA(1, 2, 3) funcB(4, 5) funcC(42)