Aquí podría ser tu PUBLICIDAD


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

votos
1140

¿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 de Python? Por ejemplo, digamos que tengo un módulo foo, y tengo una cadena cuyos contenidos son bar. ¿Cuál es la mejor manera de llamar foo.bar()?

Necesito obtener el valor de retorno de la función, que es la razón por la que no uso eval. Descubrí cómo hacerlo usando evalpara definir una función temporal que devuelve el resultado de esa llamada a la función, pero espero que haya una forma más elegante de hacerlo.

Publicado el 06/08/2008 a las 04:36
fuente por usuario ricree
En otros idiomas...        العربية       

10 respuestas

votos
1388

Asumiendo módulo foocon método bar:

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

En la medida de lo posible, las líneas 2 y 3 se pueden comprimir para:

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

si eso tiene más sentido para tu caso de uso. Puede usarlo getattrde esta manera en métodos vinculados a instancias de clase, métodos de nivel de módulo, métodos de clase ... la lista continúa.

Respondida el 06/08/2008 a las 04:57
fuente por usuario Patrick Johnmeyer


Aquí podría ser tu PUBLICIDAD


votos
387
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.

Respondida el 07/05/2009 a las 01:45
fuente por usuario sastanin

votos
229

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

module = __import__('foo')
func = getattr(module, 'bar')
func()
Respondida el 07/08/2008 a las 12:35
fuente por usuario HS.

votos
77

Sólo una contribución sencilla. Si la clase que necesitamos ejemplo se encuentra 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 una clase:

def sampleFunc(arg):
    print('you called sampleFunc({})'.format(arg))

globals()['sampleFunc']('sample arg')
Respondida el 19/08/2012 a las 10:40
fuente por usuario Sourcegeek

votos
64

Dada una cadena, con una ruta de Python completa a una función, así es como me fui de conseguir 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()
Respondida el 16/10/2013 a las 01:24
fuente por usuario ferrouswheel

votos
30

La respuesta (espero) nadie quería

Eval como el comportamiento

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

Por qué no añadir auto-importación

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

En caso de que tengamos los diccionarios adicionales queremos comprobar

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")()
Respondida el 09/04/2014 a las 11:17
fuente por usuario 00500005

votos
26

La mejor respuesta de acuerdo con el FAQ de programación 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 tienen que coincidir con los nombres de las funciones. Esta es también la técnica principal utilizada para emular un constructo caso

Respondida el 24/10/2016 a las 10:20
fuente por usuario user3946687

votos
18

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

myFnName  = "MyFn"
myAppName = "MyApp"
app = sys.modules[myAppName]
fn  = getattr(app,myFnName)
Respondida el 14/02/2012 a las 06:55
fuente por usuario trubliphone

votos
15

Prueba esto. Si bien esto sigue utilizando eval, sólo lo utiliza para llamar a la función del contexto actual . A continuación, tiene la función real de utilizar como desee.

El principal beneficio para mí de esto es que usted recibirá errores relacionados con eval-en el punto de llamar a la función. Por lo que recibirá sólo los errores relacionados con la función cuando se llama.

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)
Respondida el 07/12/2016 a las 03:29
fuente por usuario tvt173

votos
13

nada de lo que fue sugerido me ayudó. Me hizo descubrir esto, sin embargo.

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

Estoy usando Python 2,66

Espero que esto ayude

Respondida el 28/12/2012 a las 05:56
fuente por usuario Natdrip


Aquí podría ser tu PUBLICIDAD