web-dev-qa-db-fra.com

Utilisez une chaîne pour appeler la fonction dans Python

Il y a quelques jours, je cherchais sur le net et j'ai trouvé un article intéressant sur les dictionnaires python. Il s'agissait d'utiliser les touches du dictionnaire pour appeler une fonction. Dans cet article, l'auteur a défini certains fonctions, puis un dictionnaire avec une clé exactement la même que le nom de la fonction. Ensuite, il pourrait obtenir un paramètre d'entrée de l'utilisateur et appeler la même méthode (quelque chose comme l'implémentation de la casse) Après cela, j'ai réalisé la même chose mais en quelque sorte différent. Je veux pour savoir comment je peux l'implémenter. Si j'ai une fonction:

def fullName( name = "noName", family = "noFamily" ):
    return name += family

Et maintenant, si j'ai une chaîne comme celle-ci:

myString = "fullName( name = 'Joe', family = 'Brand' )"

Existe-t-il un moyen d'exécuter cette requête et d'obtenir un résultat: JoeBrand
Par exemple, je me souviens que nous pourrions donner une chaîne à l'instruction exec () et elle le fait pour nous. Mais je ne suis pas sûr de ce cas particulier, et je ne connais pas non plus le moyen efficace en Python. Et je serai également très reconnaissant de m'aider à gérer la valeur de retour de cette fonction, par exemple dans mon cas, comment puis-je imprimer le nom complet renvoyé par cette fonction?

27
user435245

Vous pouvez utiliser eval () :

myString = "fullName( name = 'Joe', family = 'Brand' )"
result = eval(myString)

Attention cependant, eval() est considéré comme un mal par beaucoup de gens.

29

Cela ne répond pas exactement à votre question, mais peut-être que cela aide néanmoins:

Comme mentionné, eval doit être évité si possible. Une meilleure façon imo est d'utiliser le déballage du dictionnaire. Ceci est également très dynamique et moins sujet aux erreurs.

Exemple:

def fullName(name = "noName", family = "noFamily"):
    return name + family

functionList = {'fullName': fullName}

function = 'fullName'
parameters = {'name': 'Foo', 'family': 'Bar'}

print functionList[function](**parameters)
# prints FooBar

parameters = {'name': 'Foo'}
print functionList[function](**parameters)
# prints FoonoFamily
43
Felix Kling

Je sais que cette question est assez ancienne, mais vous pourriez faire quelque chose comme ça:

argsdict = {'name': 'Joe', 'family': 'Brand'}
globals()['fullName'](**argsdict)

argsdict est un dictionnaire d'arguments, globals appelle la fonction à l'aide d'une chaîne et ** étend le dictionnaire à une liste de paramètres. Beaucoup plus propre que eval. Le seul problème réside dans le fractionnement de la chaîne. Une solution (très salissante):

example = 'fullName(name=\'Joe\',family=\'Brand\')'
# Split at left parenthesis
funcname, argsstr = example.split('(')
# Split the parameters
argsindex = argsstr.split(',')
# Create an empty dictionary
argsdict = dict()
# Remove the closing parenthesis
# Could probably be done better with re...
argsindex[-1] = argsindex[-1].replace(')', '')
for item in argsindex:
    # Separate the parameter name and value
    argname, argvalue = item.split('=')
    # Add it to the dictionary
    argsdict.update({argname: argvalue})
# Call our function
globals()[funcname](**argsdict)
8
kirbyfan64sos