2013-11-29 148 views
0

我有,我已经成功地转换成蟒蛇statment列表解析列表来创建Python代码

例如:

from operator import mul,add,sub,abs 

l = ['add(4,mul(3,abs(-3)))'] 

我在想什么,我会用它来运行这个字符串作为实际的Python代码?我应该期待输出为13.我想将列表的第0个值输入到一个函数中,该函数能够将该值作为实际的python代码运行。

+1

你为什么要这样做?无论你想要做什么,很可能有更好的方法来做到这一点。 – abarnert

+0

@abarnert我试图解析一个表达式并将其转换为python来计算一个值。但是,仔细阅读后,我不认为我可以使用exec(),因为它基于eval(),我不能使用eval()。 (作业的一部分)。我认为我将不得不以另一种方式编写这个解析器 – Liondancer

+0

这个任务说你不能使用'eval'意味着“将它转换成Python来计算一个值”这一事实首先是错误的方法。您需要解析表达式,然后根据表达式语言而不是Python来评估解析的表达式。 – abarnert

回答

2

您不想将其作为Python代码运行。你试图用一些不是Python的语言解析表达式,即使它可能表面上类似。即使它是Python的一个真正的子集,除非(例如)__import__('os').system('rm -rf /')碰巧是要清除硬盘驱动器的语言中的有效字符串,那么使用evalexec是一个坏主意。

如果语法是Python的一个合适的子集,仍然可以使用ast模块进行解析,然后为解析的节点编写自己的解释器。然而,我认为你真正想在这里做的是为你的非常简单的语言构建一个非常简单的解析器。这是学习如何使用像pyparsing这样的解析库或像pybison这样的解析器生成器工具或从头构建简单的递归下降解析器的绝佳机会。但对于这样简单的事情,即使是基本的字符串操作(分割/查找括号)也应该足够。

下面是一个故意愚蠢的例子(你绝对,如果你想有一个好成绩不应该上交),以显示它是多么容易:

import operator 

OPERATORS = operator.__dict__ 

def evaluate_expression(expr): 
    try: 
     return int(expr) 
    except ValueError: 
     pass 
    op, _, args = expr.rpartition('(') 
    rest, _, thisop = op.rpartition(',') 
    args = args.rstrip(')').split(',') 
    argvalues = map(int, args) 
    thisvalue = OPERATORS[thisop](*argvalues) 
    if rest: 
     return evaluate_expression('{},{}'.format(rest, thisvalue)) 
    return thisvalue 

while True: 
    expr = input() 
    print(evaluate_expression(expr)) 

通常情况下,你想找到的最外面的表达式,然后以递归方式评估它 - 这比找到最右边的要容易得多,将其替换为字符串并递归评估结果。再说一遍,我只是表明即使你不以简单的方式去做,它是多么容易。

2

使用exec这样的:

exec('add(4,mul(3,abs(-3)))') 

这应该工作

更多exec

+0

我在我的解释器中试过,我没有得到任何输出=/ – Liondancer

+1

@Liondancer因为代码里面没有打印语句。把它改成'print add ....' – sashkello

+1

yes你需要做'exec('print add(4,mul(3,abs(-3)))')' – Serial

1

,因为你正在评估一个表达式,EVAL会适合你比EXEC更好。例如:

x = -3 
y = eval('add(4,mul(3,abs(x)))') 
print y 

注意的exec和eval的安全含义,因为它们可以执行任意代码,例如包括删除您可以访问所有文件,安装木马程序到您的文档文件等

退房python 2.6+也是ast.literal_eval

+0

'ast .literal_eval'只评估文字;它不适用于函数调用的表达式。 (这是_why_首先是安全的。) – abarnert

1

如果要评估Python表达式,请使用eval。这将返回评估表达式的值。因此,举例来说:

>>> eval(l[0]) 
13 
>>> results = [eval(expr) for expr in l] 
>>> results 
[13] 

但是,任何时候你发现自己使用eval(或exec或相关的功能),你总是做错事。 This blog post解释了一些原因。

+0

是的,我从我的搜索中了解到这一点。到目前为止,我已经将表达式解析为整数和字符串列表,然后我将它们放在一起并将代码运行到exec()。但是我不允许使用为我评估表达式的函数,所以我需要以另一种方式来做。感谢您的帮助,谢谢!所有这些帖子都是我的问题的正确答案。我需要针对我的情况提出一个不同的问题。 – Liondancer