2016-08-09 3 views
3

Ich arbeite an einem "Copy-Paste-Calculator", der mathematische Ausdrücke in der Zwischenablage des Systems erkennt, auswertet und die Antwort in die Zwischenablage kopiert, um sie einzufügen. Obwohl der Code die eval() - Funktion verwendet, bin ich nicht besonders beunruhigt, wenn man bedenkt, dass der Benutzer normalerweise weiß, was er kopiert. Davon abgesehen möchte ich einen besseren Weg finden, ohne den Berechnungen ein Handicap zu geben (= z. B. die Fähigkeit, Multiplikationen oder Exponenten zu berechnen).Einen mathematischen Ausdruck ohne eval() auf Python3 auswerten

Hier die wichtigen Teile meines Code:

#! python3 
import pyperclip, time 

parsedict = {"×": "*", 
      "÷": "/", 
      "^": "**"} # Get rid of anything that cannot be evaluated 

def stringparse(string): # Remove whitespace and replace unevaluateable objects 
    a = string 
    a = a.replace(" ", "") 
    for i in a: 
     if i in parsedict.keys(): 
      a = a.replace(i, parsedict[i]) 
    print(a) 
    return a 

def calculate(string): 
    parsed = stringparse(string) 
    ans = eval(parsed) # EVIL!!! 
    print(ans) 
    pyperclip.copy(str(ans)) 

def validcheck(string): # Check if the copied item is a math expression 
    proof = 0 
    for i in mathproof: 
     if i in string: 
      proof += 1 
     elif "http" in string: #TODO: Create a better way of passing non-math copies 
      proof = 0 
      break 
    if proof != 0: 
     calculate(string) 

def init(): # Ensure previous copies have no effect 
    current = pyperclip.paste() 
    new = current 
    main(current, new) 

def main(current, new): 
    while True: 
     new = pyperclip.paste() 
     if new != current: 
      validcheck(new) 
      current = new 
      pass 
     else: 
      time.sleep(1.0) 
      pass 

if __name__ == "__main__": 
    init() 

F: Was soll ich anstelle von eval(), um die Antwort zu berechnen?

Antwort

5

sollten Sie ast.parse verwenden:

import ast 

try: 
    tree = ast.parse(expression, mode='eval') 
except SyntaxError: 
    return # not a Python expression 
if not all(isinstance(node, (ast.Expression, 
     ast.UnaryOp, ast.unaryop, 
     ast.BinOp, ast.operator, 
     ast.Num)) for node in ast.walk(tree)): 
    return # not a mathematical expression (numbers and operators) 
result = eval(compile(tree, filename='', mode='eval')) 

Beachten Sie, dass alle der Einfachheit halber dies ermöglicht die unäre Operatoren (+, -, ~, not) sowie die arithmetische und bitweise binäre Operatoren (+, -, *, /, %, //**, <<, >>, &, |, ^) aber nicht die logischen oder Vergleichsoperatoren. Es sollte einfach sein, die zulässigen Operatoren zu verfeinern oder zu erweitern.

Verwandte Themen