2 Stimmen

Python eval funktioniert nicht innerhalb einer Funktion

Ich benutze cette Code zur Auswertung mathematischer Ausdrücke aus Zeichenketten. Und es funktioniert:

#!/usr/bin/env python
from __future__ import division
from math import *

expression = raw_input()

# Math functions
safe_list = ['math', 'factorial', 'acos', 'asin', 'atan', 'atan2', 'ceil', 'cos', 'cosh', 'degrees', 'e', 'exp', 'fabs', 'floor', 'fmod', 'hypot', 'log', 'log10', 'modf', 'pi', 'pow', 'radians', 'sin', 'sinh', 'sqrt', 'tan', 'tanh'] 

# Create safe directory
safe_dict = dict([(key, locals().get(key, None)) for key in safe_list]) 
safe_dict['abs'] = abs

result = eval(expression, {"__builtins__": None}, safe_dict)
print result

Ich habe es in eine Funktion wie diese verpackt:

#!/usr/bin/env python
from __future__ import division
from math import *

def calculate(expression):
    # Math functions
    safe_list = ['math', 'factorial', 'acos', 'asin', 'atan', 'atan2', 'ceil', 'cos', 'cosh', 'degrees', 'e', 'exp', 'fabs', 'floor', 'fmod', 'hypot', 'log', 'log10', 'modf', 'pi', 'pow', 'radians', 'sin', 'sinh', 'sqrt', 'tan', 'tanh'] 

    # Create safe directory
    safe_dict = dict([(key, locals().get(key, None)) for key in safe_list]) 
    safe_dict['abs'] = abs

    result = eval(expression, {"__builtins__": None}, safe_dict)
    if isinstance(result, float) and result.is_integer():
        result = int(result)
    print result

expr = raw_input()
calculate(expr)

Und es funktioniert immer noch für die grundlegenden Operationen, aber keine der Funktionen, die in safe_dict arbeiten. 5**5 funktioniert mit beiden Programmen, aber sin(pi) mit dem ersten Codebeispiel funktioniert, mit dem zweiten nicht. Der Traceback lautet

Traceback (most recent call last):
  File "stack.py", line 20, in <module>
    calculate(expression)
  File "stack.py", line 14, in calculate
    result = eval(expression, {"__builtins__": None}, safe_dict)
  File "<string>", line 1, in <module>
TypeError: 'NoneType' object is not callable

7voto

BrenBarn Punkte 228691

Der Grund dafür ist, dass die Funktionen, die Sie aus dem Mathematikmodul importieren, keine lokalen Variablen innerhalb der Funktion sind; sie sind global. Wenn Sie also locals() lesen und in das Diktat einfügen, wird für jede einzelne Variable None eingefügt. Sie würden dies sehen, wenn Sie die get(key, None) und gerade zugegriffen locals()[key] direkt.

Eine bessere Möglichkeit ist die Verwendung von getattr für das Mathematikmodul. Machen Sie import math (nicht from math import * ) und tun dann safe_dict = dict((k, getattr(math, k)) for k in safe_list) .

3voto

Russell Borogove Punkte 17573

Innerhalb Ihres calculate() Funktion, locals() enthält nicht die Funktionen, die aus math . Deshalb, safe_dict ist bevölkert mit einer Vielzahl von None .

Sie könnten die safe_dict außerhalb von calculate() was auch den Vorteil hätte, dass es besser funktioniert, wenn Sie mehrere Aufrufe an calculate() .

1voto

inspectorG4dget Punkte 103745

Dies könnte daran liegen, dass Sie 'math' en safe_list y math ist ein Modul. Für mich sieht es so aus eval tut math() was dazu führt, dass er sich so verschluckt, wie er es jetzt tut.

Versuchen Sie zu entfernen 'math' de safe_list und sehen Sie, ob das überhaupt hilft.

Nebenbei bemerkt: Ich bin mir nicht sicher, ob dies wirklich der beste Weg ist, um das zu tun, was Sie tun wollen. Ich denke, dass eine Designänderung erforderlich ist.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X