Il y a une fonction eval()
en Python sur laquelle je suis tombé en jouant. Je ne peux pas penser à un cas où cette fonction est nécessaire, sauf peut-être en tant que sucre syntaxique. Quelqu'un peut-il donner un exemple?
eval
et exec
sont un moyen pratique et rapide d’obtenir du code source de façon dynamique, peut-être de le modifier un peu, puis de l’exécuter, mais c’est rarement le meilleur moyen, en particulier dans le code de production, par opposition à "rapide". et "sale" prototypes & c.
Par exemple, si je devais traiter avec des sources Python aussi dynamiques, j'aurais recours au ast module - ast.literal_eval
est BEAUCOUP plus sûr que eval
(vous pouvez l'appeler directement sous la forme chaîne de l'expression, si une seule fois et repose uniquement sur des constantes simples, ou utilisez d'abord node = ast.parse(source)
, puis conservez le node
name__, éventuellement avec des visiteurs appropriés, par exemple pour une recherche de variable, puis literal_eval
le nœud) - ou, une fois que le nœud a été correctement mis en forme et l'a vérifié pour des problèmes de sécurité, je pouvais compile
(lui donnant un objet code) et créer un nouvel objet fonction à partir de celui-ci. Beaucoup moins simple (sauf que ast.literal_eval
est aussi simple que eval
dans les cas les plus simples!), Mais plus sûr et préférable pour un code de qualité production.
Dans de nombreuses tâches, j'ai déjà vu des personnes (ab-) utiliser exec
et eval
pour, les puissantes fonctions intégrées de Python, telles que getattr
et setattr
name__, en indexant dans globals()
, etc., fournissent des solutions préférables et souvent plus simples. Pour des utilisations spécifiques telles que l'analyse JSON, les modules de bibliothèque tels que json
sont meilleurs (voir le commentaire de SilentGhost sur la réponse de l'acouphène à cette question). Etc...
L’article Wikipedia sur eval
est assez informatif et détaille diverses utilisations.
Certaines des utilisations suggérées sont:
Vous pouvez l’utiliser pour permettre aux utilisateurs de saisir leurs propres "scriptlets": small expressions (ou même de petites fonctions), permettant de personnaliser le comportement d’un complex système .
Dans ce contexte, et si vous n’avez pas à vous soucier de la sécurité (par exemple, vous avez une base d’utilisateurs bien informée), alors eval () peut être un bon choix.
Dans le passé, j’utilisais eval () pour ajouter une interface de débogage à mon application. J'ai créé un service telnet qui vous a plongé dans l'environnement de l'application en cours d'exécution. Les entrées ont été exécutées via eval () afin que vous puissiez exécuter de manière interactive des commandes Python dans l'application.
Dans un programme que j'ai écrit une fois, vous disposiez d'un fichier d'entrée dans lequel vous pouviez spécifier des paramètres géométriques à la fois comme valeurs et comme expressions python des valeurs précédentes, par exemple:
a=10.0
b=5.0
c=math.log10(a/b)
Un analyseur python a lu ce fichier d'entrée et a obtenu les données finales évaluant les valeurs et les expressions à l'aide de eval ().
Je ne prétends pas que ce soit une bonne programmation, mais je n'ai pas eu à conduire de réacteur nucléaire.
Je l'utilise comme un analyseur JSON rapide ...
r='''
{
"glossary": {
"title": "example glossary"
}
}
'''
print eval(r)['glossary']['title']
eval()
n'est normalement pas très utile. L'une des rares choses pour lesquelles je l'utilisais (eh bien, c'était exec()
en fait, mais c'est assez similaire) permettait à l'utilisateur de scripter une application que j'avais écrite en Python. S'il était écrit en C++, je devrais intégrer un interpréteur Python dans l'application.
Eval est un moyen d'interagir avec l'interpréteur Python à partir d'un programme. Vous pouvez passer des littéraux à eval et les évalue comme des expressions Python.
Par exemple -
print eval("__import__('os').getcwd()")
renverrait le répertoire de travail actuel.
à votre santé
Vous pouvez utiliser eval dans un décorateur:
#this replaces the original printNumber with a lambda-function,
#which takes no arguments and which calls the old function with
#the number 10
@eval("lambda fun: lambda: fun(10)")
def printNumber(i: int) -> None:
print("The number is %i", i)
#call
printNumber()
alors que vous ne pouvez pas utiliser d'expressions complexes comme
@lambda fun: lambda: fun(10)
def ...
ni
@(lambda fun: lambda: fun(10))
def ...
Vous ne pouvez pas utiliser d'expression lambda ici, car le décorateur doit être soit un identifiant:
@myModule.functionWithOneArg
ou un appel de fonction:
@functionReturningFunctionWithOneArg(any, "args")
Vous voyez que l'appel de la fonction eval avec une chaîne a une syntaxe valide ici, mais pas l'expression lambda. (-> https://docs.python.org/3/reference/compound_stmts.html#function-definitions )
eval () est pour une phrase, tandis qu'exec () est pour plusieurs phrases.
nous les utilisons généralement pour ajouter ou visiter des scripts, comme bash Shell.
en raison de leur capacité à exécuter des scripts d’octets dans la mémoire, si vous avez des données ou un script importants, vous pouvez les décoder et les décompresser, puis faire tout ce que vous voulez.
Je l'ai utilisé pour entrer des valeurs variables dans le programme principal:
test.py var1 = 2 var2 = True
...
var1=0
var2=False
for arg in sys.argv[1:]:
exec(arg)
Une manière grossière d'autoriser les arguments de mots clés dans le programme principal. S'il y a un meilleur moyen, faites le moi savoir!
Je viens de découvrir un bon usage de eval. J'étais en train d'écrire une suite de tests pour du code et de créer une classe de tests dans laquelle chaque méthode était un test à exécuter. Je voulais un moyen de pouvoir exécuter toutes les méthodes de test sans avoir à appeler chaque méthode individuellement. J'ai donc écrit quelque chose d'assez sale.
class Test:
def __init__(self, *args):
#bs
def test1(self):
#bs
def test2(self):
#bs
if __== "__main__":
import argparse
#argparse bs
test = Test(*bs_args)
for func in (i for i in dir(test) if i[0] != '_' and i not in test.__dict__):
print(eval('test.{func}()'.format(func = func)))
L'évaluation dynamique des cas de test arbitraires est plutôt cool. Je dois juste écrire la méthode et, après avoir enregistré, je peux l'inclure dans ma suite de tests. En ce qui concerne le code, je vérifie simplement les méthodes définies dans l’objet test et s’assure qu’il ne s’agit pas de méthodes ou d’attributs «magiques» python par défaut pour cet objet. Après cela, je peux supposer que ce sont des méthodes et peuvent être évaluées.