强制函数参数为字符串

时间:2013-04-23 01:39:47

标签: python string function arguments

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

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 个答案:

答案 0 :(得分:2)

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

使用eval作为美化计算器是一个高度可疑的想法。用户可以传递各种恶意Python代码。 如果你要去做,你应该尽可能少地提供运行代码的环境。传入你自己的全局dict,其中只包含允许用户使用的变量参考。

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

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

答案 1 :(得分: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'),您的计算器将删除您的作业。

答案 2 :(得分: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

甚至有一个方便的功能可以将字符串转换为对象:

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

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

答案 3 :(得分: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)