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

4

I'm trying to use a dictionary to identify each function to a value, and call them through 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, it says that I can not call the function using the string I set as the value of a dictionary entry. Is there a way around this?

    
asked by anonymous 28.11.2015 / 00:41

3 answers

0

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

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

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

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

But I already had to do this for a system of plugins where the complete package ( from pacote.x.y.z import funcao ) was needed, 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
    
28.11.2015 / 11:28
2

According to this answer in SOEn. Use:

locals()["nomedafuncao"]()

or

globals()["nomedafuncao"]()

In your case, it would be:

locals()[menuOpt[1]]()
    
28.11.2015 / 00:56
2

It's simple, instead of putting a string, put the name of the function. In addition, 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]()
    
28.11.2015 / 01:38