2010-11-09 19 views
16

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 certaines fonctions, puis un dictionnaire avec une clé exactement identique au nom de la fonction. Puis il pourrait obtenir un paramètre d'entrée de l'utilisateur et appeler la même méthode (quelque chose comme la mise en œuvre de casse) Après cela, je me suis rendu compte de la même chose, mais en quelque sorte différent. Je veux savoir comment je peux mettre en œuvre cela. Si j'ai une fonction:Utiliser une chaîne pour appeler la fonction en Python

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

Et maintenant, si j'ai une chaîne comme ceci:

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

est-il un moyen d'exécuter cette requête et obtenir un résultat: JoeBrand
Par exemple quelque chose Je me souviens que nous pourrions donner une chaîne à la commande exec() et c'est ce qu'elle fait pour nous. Mais je ne suis pas sûr de ce cas particulier, et je ne connais pas la manière efficace de Python. Et aussi je serai si reconnaissant de m'aider à gérer ces fonctions de retour de valeur, par exemple dans mon cas comment puis-je imprimer le nom complet retourné par cette fonction?

+2

vous fonctionnez est va ... Aucun retour utilisation + au lieu de + = – Ant

+1

Pour ce faire, utilisez: getattr (myString, 'fullName') (name = 'Joe', family = 'Brand') [voir la question en double liée en haut de la page] – Stew

+0

[Note: getattr() est utilisé par la première réponse de la question que ce post duplique, mais n'est pas mentionné ci-dessous. Je pensais qu'il serait utile d'apparaître sur cette page elle-même, donc je plie la convention contre la réponse aux questions dans les commentaires.] – Stew

Répondre

26

Vous pouvez utiliser eval():

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

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

+0

Merci d'avance, mais est-ce que cela renvoie une valeur à la fonction si je la stocke dans une variable? – user435245

+0

Oui, c'est le cas. Voir ma réponse mise à jour. –

+2

Mieux répondre: http: // stackoverflow.com/questions/3061/call-a-function-from-a-string-with-the-functions-name-in-python – Framester

37

Cela ne veut pas exactement répondre à votre question, mais peut-être il aide néanmoins:

Comme mentionné précédemment, eval doit être évitée si possible. Un meilleur moyen est d'utiliser le déballage du dictionnaire. C'est aussi très dynamique et moins sujette 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 
+3

+1 pour ne pas suggérer 'eval' – MAK

6

Je sais que cette question est assez vieux, mais vous pouvez faire quelque chose comme ceci:

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

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

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) 
+0

La seule et unique solution. Si ce code résidait dans un module, et que ce module serait rechargé après que le code de 'fullName' ait été changé, alors les changements sont effectifs dans l'appel suivant' fullName'. La réponse de Felix Kling n'a pas cette propriété car la fonction est mise en cache dans 'functionList', et nous ne parlerons même pas de la gravité de l'idée' eval'. –

Questions connexes