How to use a dictionary value to call a specific Python function?

Asked

Viewed 655 times

4

I’m trying to use a dictionary to identify each function to a value, and call them over the program. My code is below (example):

#!/usr/bin/env python
menuOpt = {
    1 : "valor",
}
#Main
if __name__ == "__main__":
    print "Valor"
    menuOpt[1]()
def valor():
    x = 8
    y = 7
    o = x*y
    print o

However, when I run it, I get the following error:

Valor
Traceback (most recent call last):
  File "teste.py", line 8, in <module>
    menuOpt[1]()
TypeError: 'str' object is not callable

Apparently, he says I can’t call the function using the string I define as a dictionary input value. There is a way around this?

3 answers

2

According to that answer on Soen. Use:

locals()["nomedafuncao"]()

or

globals()["nomedafuncao"]()

In your case, it would be:

locals()[menuOpt[1]]()

2

It is simple, instead of putting a string, put the name of the function. Also, you can structure your program a little better:

def valor():
    """ Função a ser chamada """
    print('valor')

menuOpt = {
    1 : valor,
}

if __name__ == '__main__':
    menuOpt[1]()

0


I don’t know exactly what you want to do, but the simplest answer for you is:

# nome = menuOpt[1]
globals().get(nome)()

But it is good not to let the code die if the name does not exist or if the name is not 'searchable', this can be achieved (using the: EAFP 'it is easier to ask for forgiveness than permission') so:

# nome = menuOpt[1]
try: 
   globals().get(nome)()
except TypeError:
   pass

But I already had to do this for a plugins system where the complete package was needed (from pacote.x.y.z import funcao), so I needed something more elaborate, like:

def getattrfull(path):
    """
    Obtem um atributo de um caminho separado por '.' simulando um `import`

    Exemplo para simular 'from os import name as sistema':
    >>> sistema = getattrfull('os.name')
    >>> sistema
    'posix'

    Funciona para funcoes/classes/etc:
    >>> decode = getattrfull('json.loads')
    >>> decode('[1, 2, 3, 4]')
    [1, 2, 3, 4]

    Se o modulo ou funcao nao existir ele retorna 'None'
    >>> getattrfull('eu.nao.existo')
    None
    """

    # Primeiro tem que separar o modulo da funcao/classe/qualquercoisa
    # XXX: o codigo só funciona se tiver ".", ou seja, não pega nomes 
    #      locais ao arquivo atual, para fazer comportamento semelhante use:
    #      >>> globals().get(nome)
    module_name, attr_name = path.rsplit(".", 1)

    # importar modulo
    try:
        module = __import__(module_name, locals(), globals(), [str(attr_name)])
    except ImportError:
        return None

    # procurar pelo atributo
    try:
        attr = getattr(module, attr_name)
    except AttributeError:
        return None

    return attr

Browser other questions tagged

You are not signed in. Login or sign up in order to post.