Chamar uma função de um módulo usando seu nome (uma string)

votos
1k

Qual é o melhor caminho a percorrer cerca de chamar uma função dada uma string com o nome da função em um programa Python. Por exemplo, digamos que eu tenho um módulo foo, e eu tenho uma string cujo conteúdo é bar. Qual é a melhor maneira de ir sobre a chamada foo.bar()?

Eu preciso para obter o valor de retorno da função, que é por isso que eu não basta usar eval. Eu descobri como fazê-lo usando evalpara definir uma função temporária que retorna o resultado dessa chamada de função, mas eu estou esperando que existe uma maneira mais elegante de fazer isso.

Publicado 06/08/2008 em 04:36
fonte usuário
Em outras línguas...                            


10 respostas

votos
1k

Assumindo módulo foocom método bar:

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

Na medida do que se passa, as linhas 2 e 3 podem ser comprimidos para:

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

se isso faz mais sentido para o seu caso de uso. Você pode usar getattrdesta forma sobre os métodos vinculados instância de classe, métodos de nível de módulo, métodos de classe ... a lista continua.

Respondeu 06/08/2008 em 04:57
fonte usuário

votos
387
locals()["myfunction"]()

ou

globals()["myfunction"]()

locals retorna um dicionário com uma corrente tabela de símbolos local. globals retorna um dicionário com tabela de símbolos global.

Respondeu 07/05/2009 em 13:45
fonte usuário

votos
229

A solução de Patrick é provavelmente o mais limpo. Se você precisa escolher dinamicamente o módulo, bem, você pode importá-lo como:

module = __import__('foo')
func = getattr(module, 'bar')
func()
Respondeu 07/08/2008 em 12:35
fonte usuário

votos
77

Apenas uma contribuição simples. Se a classe que precisamos instância é no mesmo arquivo, podemos usar algo como isto:

# 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 exemplo:

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')

E, se não uma classe:

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

globals()['sampleFunc']('sample arg')
Respondeu 19/08/2012 em 10:40
fonte usuário

votos
64

Dado uma string, com um caminho python completa para uma função, isto é como eu fui sobre a obtenção do resultado da referida função:

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()
Respondeu 16/10/2013 em 01:24
fonte usuário

votos
30

A resposta (espero) nunca ninguém quis

Eval como o comportamento

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

Por que não adicionar auto-importação

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

No caso, temos dicionários extras queremos verificar

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

Precisamos ir mais fundo

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")()
Respondeu 09/04/2014 em 11:17
fonte usuário

votos
26

A melhor resposta de acordo com a programação FAQ Python seria:

functions = {'myfoo': foo.bar}

mystring = 'myfoo'
if mystring in functions:
    functions[mystring]()

A principal vantagem desta técnica é que as cordas não precisa coincidir com os nomes das funções. Este é também o principal técnica utilizada para emular uma construo caso

Respondeu 24/10/2016 em 13:20
fonte usuário

votos
18

Por que vale a pena, se for necessário para passar a função (ou classe) nome e nome do aplicativo como uma string, então você poderia fazer isso:

myFnName  = "MyFn"
myAppName = "MyApp"
app = sys.modules[myAppName]
fn  = getattr(app,myFnName)
Respondeu 14/02/2012 em 06:55
fonte usuário

votos
15

Tente isto. Enquanto isto ainda usa eval, ele só usa-lo para chamar a função do contexto atual . Então, você tem a função real para usar como quiser.

O principal benefício para mim com isso é que você vai obter quaisquer erros relacionados com o eval no ponto de invocar a função. Então você vai ter apenas os erros relacionados função, quando você ligar.

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)
Respondeu 07/12/2016 em 18:29
fonte usuário

votos
13

nada do que foi sugerido me ajudou. Eu descobri isso embora.

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

Eu estou usando python 2,66

Espero que isto ajude

Respondeu 28/12/2012 em 17:56
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more