J'utilise la classe suivante pour stocker facilement les données de mes chansons.
class Song:
"""The class to store the details of each song"""
attsToStore=('Name', 'Artist', 'Album', 'Genre', 'Location')
def __init__(self):
for att in self.attsToStore:
exec 'self.%s=None'%(att.lower()) in locals()
def setDetail(self, key, val):
if key in self.attsToStore:
exec 'self.%s=val'%(key.lower()) in locals()
Je pense que c'est juste beaucoup plus extensible que d'écrire un if/else
bloc. Cependant, eval
semble être considéré comme une mauvaise pratique et dangereux à utiliser. Si oui, quelqu'un peut-il m'expliquer pourquoi et me montrer une meilleure façon de définir la classe ci-dessus?
exec/eval
et ne saviez toujours passetattr
?Réponses:
Oui, utiliser eval est une mauvaise pratique. Pour ne citer que quelques raisons:
Dans votre cas, vous pouvez utiliser setattr à la place:
ÉDITER:
Dans certains cas, vous devez utiliser eval ou exec. Mais ils sont rares. Utiliser eval dans votre cas est certainement une mauvaise pratique. Je mets l'accent sur les mauvaises pratiques car eval et exec sont souvent utilisés au mauvais endroit.
MODIFIER 2:
Il semble que certains ne soient pas d'accord sur le fait que l'évaluation est «très dangereuse et peu sûre» dans le cas de l'OP. Cela pourrait être vrai pour ce cas précis, mais pas en général. La question était générale et les raisons que j'ai énumérées sont également valables pour le cas général.
EDIT 3: réorganisé les points 1 et 4
la source
eval
n'ont rien à voir les unes avec les autres. Une application qui est fondamentalement mal conçue est fondamentalement mal conçue.eval
n'est pas plus la cause première d'une mauvaise conception que la division par zéro ou la tentative d'importer un module dont on sait qu'il n'existe pas.eval
n'est pas incertain. Les applications ne sont pas sécurisées.calc
, et que pour ajouter des numéros, il s'exécuteprint(eval("{} + {}".format(n1, n2)))
et quitte. Maintenant, vous distribuez ce programme avec certains OS. Ensuite, quelqu'un crée un script bash qui prend des nombres d'un site de stock et les ajoute à l'aide decalc
. boom?L'utilisation
eval
est faible, ce n'est clairement pas une mauvaise pratique.Il viole le «principe fondamental du logiciel». Votre source n'est pas la somme totale de ce qui est exécutable. En plus de votre source, il y a les arguments pour
eval
, qui doivent être clairement compris. Pour cette raison, c'est l'outil de dernier recours.C'est généralement le signe d'un design irréfléchi. Il y a rarement une bonne raison pour un code source dynamique, construit à la volée. Presque tout peut être fait avec la délégation et d'autres techniques de conception OO.
Cela conduit à une compilation à la volée relativement lente de petits morceaux de code. Une surcharge qui peut être évitée en utilisant de meilleurs modèles de conception.
En note de bas de page, entre les mains de sociopathes dérangés, cela peut ne pas bien fonctionner. Cependant, lorsqu'ils sont confrontés à des utilisateurs ou administrateurs sociopathes dérangés, il est préférable de ne pas leur donner Python interprété en premier lieu. Entre les mains du vraiment pervers, Python peut être un handicap;
eval
n'augmente pas du tout le risque.la source
eval
s'agit d'une sorte de «vulnérabilité de sécurité». Comme si Python - lui-même - n'était pas simplement un ensemble de sources interprétées que n'importe qui pouvait modifier. Lorsqu'on est confronté à «l'évaluation est une faille de sécurité», vous ne pouvez que supposer que c'est une faille de sécurité entre les mains des sociopathes. Les programmeurs ordinaires modifient simplement la source Python existante et causent directement leurs problèmes. Pas indirectement pareval
magie.while True: pass
serait difficile de nettoyer avec une sorte de fuite.eval()
, car c'est une chaîne. Le code du "monde extérieur" ne peut pas être nettoyé. Les chaînes du monde extérieur ne sont que des chaînes. Je ne sais pas de quoi vous parlez. Vous devriez peut-être fournir un article de blog plus complet et un lien vers celui-ci ici.Dans ce cas, oui. Au lieu de
vous devez utiliser la fonction intégrée
setattr
:la source
Oui, ça l'est:
Pirater en utilisant Python:
Le code ci-dessous répertorie toutes les tâches exécutées sur une machine Windows.
Sous Linux:
la source
Il convient de noter que pour le problème spécifique en question, il existe plusieurs alternatives à l'utilisation
eval
:Le plus simple, comme indiqué, consiste à utiliser
setattr
:Une approche moins évidente consiste à mettre à jour
__dict__
directement l'objet de l' objet. Si tout ce que vous voulez faire est d'initialiser les attributs surNone
, c'est moins simple que ce qui précède. Mais considérez ceci:Cela vous permet de transmettre des arguments de mot-clé au constructeur, par exemple:
Cela vous permet également de rendre votre utilisation
locals()
plus explicite, par exemple:... et, si vous voulez vraiment attribuer
None
les attributs dont les noms se trouvent danslocals()
:Une autre approche pour fournir un objet avec des valeurs par défaut pour une liste d'attributs consiste à définir la
__getattr__
méthode de la classe :Cette méthode est appelée lorsque l'attribut nommé n'est pas trouvé de la manière normale. Cette approche est un peu moins simple que de simplement définir les attributs dans le constructeur ou de mettre à jour le
__dict__
, mais elle a le mérite de ne pas créer réellement l'attribut à moins qu'il n'existe, ce qui peut réduire considérablement l'utilisation de la mémoire de la classe.Le point de tout cela: il y a beaucoup de raisons, en général, à éviter
eval
- le problème de sécurité de l'exécution de code que vous ne contrôlez pas, le problème pratique du code que vous ne pouvez pas déboguer, etc. Mais une raison encore plus importante est-ce que généralement, vous n'avez pas besoin de l'utiliser. Python expose tellement de ses mécanismes internes au programmeur que vous avez rarement vraiment besoin d'écrire du code qui écrit du code.la source
__dict__
directement l'objet, donnez à l'objet un objet dictionnaire réel, soit par héritage, soit comme attribut.__setattr__
remplacement, ce qui pourrait conduire à des résultats inattendus.setattr()
n'a pas ce problème.D'autres utilisateurs ont souligné comment votre code peut être modifié pour ne pas dépendre de
eval
; Je vais proposer un cas d'utilisation légitimeeval
, celui que l'on trouve même dans CPython: testing .Voici un exemple que j'ai trouvé dans
test_unary.py
lequel un test pour savoir si(+|-|~)b'a'
lève unTypeError
:L'usage n'est clairement pas une mauvaise pratique ici; vous définissez l'entrée et observez simplement le comportement.
eval
est pratique pour les tests.Jetez un oeil à cette recherche pour
eval
, effectuée sur le dépôt git CPython; les tests avec eval sont largement utilisés.la source
Quand
eval()
est utilisé pour traiter l'entrée fournie par l'utilisateur, vous autorisez l'utilisateur à Drop-to-REPL en fournissant quelque chose comme ceci:Vous pouvez vous en tirer, mais normalement vous ne voulez pas de vecteurs pour l'exécution de code arbitraire dans vos applications.
la source
En plus de la réponse @Nadia Alramli, puisque je suis nouveau sur Python et que je voulais vérifier comment l'utilisation
eval
affectera les horaires , j'ai essayé un petit programme et ci-dessous se trouvaient les observations:la source