2017-07-17 1 views
0

Je me demande s'il y a un moyen simple d'éviter d'utiliser eval pour le code suivant:Alternative à eval() pour évaluer les expressions de chaîne

eval('6001 >= 6005') 

Je cherchais depuis quelques heures en essayant de trouver simple alternative après l'apprentissage eval n'est pas une bonne pratique, surtout quand vous ne savez pas qui va utiliser le programme.

L'arrière-plan à mon utilisation de c'est quelque chose comme ceci:

chacune des deux variables de comparaison sera une valeur d'une colonne de dataframe de pandas géants, il pourrait donc aussi ressembler à ceci:

eval('"my_city_name" == "your_city_name"') 

Toute aide est grandement appréciée! Merci

+0

L'évaluation de pandas est différente de la fonction eval. Ce n'est pas dangereux. Cependant, vous avez beaucoup d'alternatives comme 'query' et l'indexation booléenne. Vous devez cependant montrer un exemple d'entrée-sortie. – ayhan

+0

est eval pandas sûr? J'ai essayé un hack que j'ai vu quelque part comme ça: 'pandas.eval (input())' et il ne s'est pas cassé comme il aurait dû. Bien qu'il n'y ait pas de sortie, il a juste gelé le programme, donc je n'étais pas sûr. – jGraves

+0

Eh bien, il ne supporte que les opérations arithmétiques, donc je ne sais pas comment cela serait dangereux. Quelle a été votre contribution? – ayhan

Répondre

1

Vous pourriez éviter les eval() en mettant en œuvre les comparaisons que vous souhaitez autoriser:

STRINGS = ['6001 >= 6005', '"my_city_name" == "your_city_name"', '13 != 14', '1 < 4'] 

COMPARISONS = { 
    '==': lambda a, b: a == b, 
    '!=': lambda a, b: a != b, 
    '>=': lambda a, b: a >= b, 
} 

for string in STRINGS: 
    operand1, comparison, operand2 = string.split() 

    if comparison in COMPARISONS: 
     print(string, (COMPARISONS[comparison])(operand1, operand2)) 
    else: 
     print(string, "Unknown comparison") 

Ceci est juste un exemple, en réalité, vous aurez besoin de faire quelques vérifications de type, la conversion de nombre et ainsi de suite, mais la clé est de décider quelles comparaisons sont importantes pour vous.

+0

J'y pensais aussi, mais pour mon application, ce serait plus facile si la chaîne n'était pas scindée au cas où l'un des opérandes aurait plus d'un mot. J'ai supposé que je pouvais avoir de la logique pour traiter cette affaire, mais je voulais juste vérifier ici d'abord si quelqu'un avait des moyens rapides et intelligents de contourner cela. Merci pour le conseil! – jGraves

+0

a fini par faire une retombée de ceci qui a été approvisionné à mon application, après avoir fait plus de recherches sur des alternatives à 'eval()', semble qu'il n'y en a pas! Merci pour la contribution! – jGraves

0

Voici ce que je fini avec:

def transform(self, attribute): 

    try: 
     attribute = float(attribute) 
     if math.isnan(attribute): 
      attribute = "NULL" 
      print type(attribute) 
      return attribute 
    except ValueError: 
     attribute = str(attribute) 

    print type(attribute) 
    return attribute 

def equals(self, attribute, value): 
    return self.transform(attribute) == self.transform(value) 

def not_equals(self, attribute, value): 
    return self.transform(attribute) != self.transform(value) 

def greater_than(self, attribute, value): 
    return self.transform(attribute) > self.transform(value) 

def greater_than_equal(self, attribute, value): 
    return self.transform(attribute) >= self.transform(value) 

def less_than(self, attribute, value): 
    return self.transform(attribute) < self.transform(value) 

def less_than_equal(self, attribute, value): 
    return self.transform(attribute) <= self.transform(value) 

Comme je ne avais besoin d'une sélection de quelques-uns des opérateurs, ce fut la meilleure solution que je pouvais trouver. transform() est juste pour prendre soin de quelques problèmes de comparaison que j'ai rencontrés avec mon jeu de données particulier. J'espère que cela peut aider quelqu'un dans le futur! Si quelqu'un a des commentaires ou des suggestions s'il vous plaît faites le moi savoir.