我正在教一些邻里孩子用Python编程。我们的第一个项目是将一个给定为罗马数字的字符串转换为阿拉伯语值。
因此我们开发了一个函数来计算一个罗马数字的字符串,该函数接受一个字符串,并创建一个具有阿拉伯语等价物的列表以及为评估阿拉伯语等价物而进行的操作。
例如假设您在XI中输入函数将返回[1,'+',10] 如果你输入IX,函数将返回[10,' - ',1] 由于我们需要分别处理相邻值相等的情况,让我们忽略提供的值为XII的情况,因为它将返回[1,'=',1,'+',10]以及罗马是IIX的情况,因为它会返回[10,' - ',1,'=',1]
这是函数
def conversion(some_roman):
roman_dict = {'I':1,'V':5,'X':10,'L':50,'C':100,'D':500,'M',1000}
arabic_list = []
for letter in some_roman.upper():
if len(roman_list) == 0:
arabic_list.append(roman_dict[letter]
continue
previous = roman_list[-1]
current_arabic = roman_dict[letter]
if current_arabic > previous:
arabic_list.extend(['+',current_arabic])
continue
if current_arabic == previous:
arabic_list.extend(['=',current_arabic])
continue
if current_arabic < previous:
arabic_list.extend(['-',current_arabic])
arabic_list.reverse()
return arabic_list
我认为评估结果的唯一方法是使用eval()
类似
def evaluate(some_list):
list_of_strings = [str(item) for item in some_list]
converted_to_string = ''.join([list_of_strings])
arabic_value = eval(converted_to_string)
return arabic_value
我对这段代码有点紧张,因为在某些时候我读到eval在大多数情况下都很危险,因为它允许有人在你的系统中引入恶作剧。但我无法想出另一种方法来评估从第一个函数返回的列表。所以无需编写更复杂的功能。
孩子们获得了转换功能,所以即使看起来很复杂,他们也会理解罗马数字转换的过程,这是有道理的。当我们谈论评估虽然我可以看到他们迷路了。因此,我真的希望能够某种方式来评估转换函数的结果,而不需要太多复杂的代码。
对不起,如果这是扭曲的,我就是这样。 。 。
答案 0 :(得分:6)
有没有办法在不使用eval
的情况下完成eval的工作
是的,当然。一种选择是将整个事物转换为ast树并自己解析(例如,参见here)。
我对这段代码有点紧张,因为在某些时候我读到eval在大多数情况下都很危险,因为它允许有人在你的系统中引入恶作剧。
这绝对是真的。每当你考虑使用eval时,你需要考虑一下你的特定用例。真正的问题是你相信用户多少以及他们可以造成什么样的伤害?如果你将它作为一个脚本分发,并且用户只在自己的计算机上使用它,那么它确实不是问题 - 毕竟,他们不需要在你的脚本中注入恶意代码来删除它们的主目录。如果你打算在你的服务器上托管这个,这完全是另一个故事...然后你需要弄清楚字符串来自何处以及用户是否有任何方式可以修改字符串它不受信任。黑客非常聪明 1,2 所以在你的服务器上托管这样的东西通常不是一个好主意。 (我总是认为黑客比我更了解python WAY。)
1 http://blog.delroth.net/2013/03/escaping-a-python-sandbox-ndh-2013-quals-writeup/
2 http://nedbatchelder.com/blog/201206/eval_really_is_dangerous.html
答案 1 :(得分:1)
我遇到的安全 表达式评估者的唯一实现是:
它支持许多基本的Python-ish表达式,并且它允许你做的事情受到限制(因此你不会炸毁解释器或做一些邪恶的事情)。它使用python ast
模块进行解析,并对结果本身进行评估。
示例:强>
from simpleeval import simple_eval
simple_eval("21 + 21")
然后你可以扩展它并让它访问你想要的程序部分:
simple_eval("x + y", names={"x": 22, "y": 48})
或
simple_eval("do_thing(11)", functions={"do_thing": my_callback})
等等。
答案 2 :(得分:0)
你真的很接近制作一个计算器。也许你可以停下来教他们如何制作一个简单的计算器 - &gt;评估工作。然后你可以回来让罗马数字被允许使用,甚至可以用它们作为结果输出。