script otro modulos llamar lista importar funciones funcion directorio desde clases archivo python object

python - otro - Llamar a una función de un módulo usando su nombre(una cadena)



llamar funcion de otro archivo python (11)

Como esta pregunta Cómo llamar dinámicamente a los métodos dentro de una clase usando la asignación de nombre de método a una variable [duplicado] marcada como duplicada como esta, estoy publicando una respuesta relacionada aquí:

El escenario es, un método en una clase quiere llamar a otro método en la misma clase dinámicamente, he agregado algunos detalles al ejemplo original que ofrece un escenario y claridad más amplios:

class MyClass: def __init__(self, i): self.i = i def get(self): func = getattr(MyClass, ''function{}''.format(self.i)) func(self, 12) # This one will work # self.func(12) # But this does NOT work. def function1(self, p1): print(''function1: {}''.format(p1)) # do other stuff def function2(self, p1): print(''function2: {}''.format(p1)) # do other stuff if __name__ == "__main__": class1 = MyClass(1) class1.get() class2 = MyClass(2) class2.get()

Salida (Python 3.7.x)

función1: 12

función2: 12

¿Cuál es la mejor manera de llamar a una función dada una cadena con el nombre de la función en un programa Python? Por ejemplo, digamos que tengo un módulo foo , y tengo una cadena cuyo contenido es "bar" . ¿Cuál es la mejor manera de llamar a foo.bar() ?

Necesito obtener el valor de retorno de la función, por lo que no solo uso eval . Descubrí cómo hacerlo utilizando eval para definir una función temporal que devuelva el resultado de esa llamada de función, pero espero que haya una forma más elegante de hacerlo.


Dada una cadena, con una ruta completa de python a una función, esta es la forma en que traté de obtener el resultado de dicha función:

import importlib function_string = ''mypackage.mymodule.myfunc'' mod_name, func_name = function_string.rsplit(''.'',1) mod = importlib.import_module(mod_name) func = getattr(mod, func_name) result = func()


La mejor respuesta según las preguntas frecuentes de programación de Python sería:

functions = {''myfoo'': foo.bar} mystring = ''myfoo'' if mystring in functions: functions[mystring]()

La principal ventaja de esta técnica es que las cadenas no necesitan coincidir con los nombres de las funciones. Esta es también la técnica principal utilizada para emular una construcción de caso


La respuesta (espero) que nadie haya querido nunca.

Evaluar como comportamiento

getattr(locals().get("foo") or globals().get("foo"), "bar")()

¿Por qué no agregar auto-importación

getattr( locals().get("foo") or globals().get("foo") or __import__("foo"), "bar")()

En caso de que tengamos diccionarios extra queremos revisar.

getattr(next((x for x in (f("foo") for f in [locals().get, globals().get, self.__dict__.get, __import__]) if x)), "bar")()

Necesitamos ir más profundo

getattr(next((x for x in (f("foo") for f in ([locals().get, globals().get, self.__dict__.get] + [d.get for d in (list(dd.values()) for dd in [locals(),globals(),self.__dict__] if isinstance(dd,dict)) if isinstance(d,dict)] + [__import__])) if x)), "bar")()


La solución de Patrick es probablemente la más limpia. Si también necesita recoger dinámicamente el módulo, puede importarlo como:

module = __import__(''foo'') func = getattr(module, ''bar'') func()


Nada de lo sugerido me ayudó. Sin embargo, descubrí esto.

<object>.__getattribute__(<string name>)(<params>)

Estoy usando python 2.66

Espero que esto ayude


Para lo que vale la pena, si necesita pasar el nombre de la función (o clase) y el nombre de la aplicación como una cadena, entonces podría hacer esto:

myFnName = "MyFn" myAppName = "MyApp" app = sys.modules[myAppName] fn = getattr(app,myFnName)


Prueba esto. Si bien esto todavía usa eval, solo lo usa para invocar la función del contexto actual . Entonces, tienes la función real para usar como quieras.

El principal beneficio para mí de esto es que obtendrás cualquier error relacionado con la evaluación al momento de invocar la función. Entonces solo obtendrás los errores relacionados con la función cuando llames.

def say_hello(name): print ''Hello {}!''.format(name) # get the function by name method_name = ''say_hello'' method = eval(method_name) # call it like a regular function later args = [''friend''] kwargs = {} method(*args, **kwargs)


Solo una simple aportación. Si la clase que necesitamos para la instancia está en el mismo archivo, podemos usar algo como esto:

# Get class from globals and create an instance m = globals()[''our_class'']() # Get the function (from the instance) that we need to call func = getattr(m, ''function_name'') # Call it func()

Por ejemplo:

class A: def __init__(self): pass def sampleFunc(self, arg): print(''you called sampleFunc({})''.format(arg)) m = globals()[''A'']() func = getattr(m, ''sampleFunc'') func(''sample arg'') # Sample, all on one line getattr(globals()[''A''](), ''sampleFunc'')(''sample arg'')

Y, si no es una clase:

def sampleFunc(arg): print(''you called sampleFunc({})''.format(arg)) globals()[''sampleFunc''](''sample arg'')


Suponiendo módulo foo con bar método:

import foo method_to_call = getattr(foo, ''bar'') result = method_to_call()

En lo que va, las líneas 2 y 3 se pueden comprimir para:

result = getattr(foo, ''bar'')()

Si eso tiene más sentido para su caso de uso. Puede utilizar getattr de esta manera en los métodos enlazados de instancia de clase, los métodos de nivel de módulo, los métodos de clase ... y la lista continúa.


locals()["myfunction"]()

o

globals()["myfunction"]()

locals devuelve un diccionario con una tabla de símbolos local actual. globals devuelve un diccionario con tabla de símbolos global.