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 02:36
fonte usuário
Em outras línguas...                            


12 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 02:57
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 10:35
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 11:45
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 03:55
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 08:40
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 14:56
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 15/10/2013 em 23: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 09: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 12:20
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 16:29
fonte usuário

votos
0

Como esta pergunta Como chamar dinamicamente métodos dentro de uma classe usando atribuição método nome a uma variável [duplicado] marcado como uma duplicata como este, estou postando uma resposta relacionada aqui:

O cenário é, um método em uma classe quer chamar outro método na mesma classe dinamicamente, eu adicionei alguns detalhes a exemplo original que oferece algum cenário e clareza mais ampla:

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

Saída (3.7.x Python)

function1: 12

function2: 12

Respondeu 26/03/2019 em 16:15
fonte usuário

votos
0

Esta é uma resposta simples, isso permitirá que você para limpar a tela, por exemplo. Há dois exemplos abaixo, com eval e exec, que serão impressas 0 no topo após a limpeza (se você estiver usando o Windows, mude clearpara cls, usuários de Linux e Mac deixar como é, por exemplo) ou apenas executá-lo, respectivamente.

eval("os.system(\"clear\")")
exec("os.system(\"clear\")")
Respondeu 28/08/2019 em 18:46
fonte usuário

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