1

所以,我的代码是这样的:

def func(s,x):
   return eval(s.replace('x',x)

#Example:
>> func('x**2 + 3*x',1)
4

函数的第一个参数func必须是字符串,因为该函数eval只接受字符串或代码对象。但是,我想在一种计算器中使用此功能,例如,用户在其中键入2 + sin(2*pi-0.15) + func(1.8*x-32,273)并获得表达式的答案,而且总是不得不在表达式内部写上引号,这很烦人func()

有没有办法让python理解s参数总是一个字符串,即使它不在引号之间?

4

4 回答 4

2

不,这是不可能的。您不能在 Python 解释器解析和评估之前拦截它1.8*x-32

用作eval美化计算器是一个非常值得怀疑的想法。用户可以传入各种恶意 Python 代码。如果你打算这样做,你应该为代码运行提供尽可能小的环境。传入你自己的全局变量dict,只包含允许用户引用的变量。

return eval(s, {'x': x})

除了更安全之外,这也是替代x表达式的更好方法。

于 2013-04-23T01:44:11.600 回答
1

你可以让它处理这两种情况:

def func(s, x=0):
    if isinstance(s, basestring):
        # x is in the scope, so you don't need to replace the string
        return eval(s)
    else:
        return s

和输出:

>>> from math import *
>>> func('2 + sin(2*pi-0.15) + func(1.8*x-32,273)')
    -30.1494381324736
>>> func('x**2 + 3*x', 1)
    4

注意:eval可以做的不仅仅是添加数字。我可以打字__import__('os').system('rm /your/homework.doc'),你的计算器会删除你的作业。

于 2013-04-23T01:43:37.423 回答
1

一句话:不,如果我理解你的话。

在更多的情况下,您可以通过制作x一个特殊的对象来解决这个问题。这就是 Python 数学库SymPy的工作原理。例如:

>>> from sympy import Symbol
>>> x = Symbol('x')
>>> x**2+3*x
x**2 + 3*x
>>> (x**2+3*x).subs(x,1)
4

甚至还有一个方便的函数可以将字符串转换为 sympy 对象:

>>> from sympy import sympify, pi
>>> sympify("x**2 - sin(x)")
x**2 - sin(x)
>>> _.subs(x, pi)
pi**2

所有关于不受信任的用户输入的警告都会保留。[我懒得检查代码路径上是否使用了evalor ,而且正如他们所说,每个武器都已加载,甚至是未加载的武器。]execsympify

于 2013-04-23T01:56:13.353 回答
0

你可以写一个解释器:

import code

def readfunc(prompt):
    raw = input(prompt)
    if raw.count(',')!=1:
        print('Bad expression: {}'.format(raw))
        return ''
    s, x = raw.split(',')
    return '''x={}; {}'''.format(x, s)

code.interact('Calc 0.1', readfunc)
于 2013-04-23T02:25:56.387 回答