我总是厌倦在任何语言中使用eval,但我想不出更好的方法来做两件事。从我读过的所有内容来看,evIl(这很糟糕)。任何想法都表示赞赏。 我有一个带字典的模块,可以根据你从另一个模块调用它的方式来调用函数或设置属性
module Config
some_dict = {1: ["desc 1", "callfunction1()"],
2: ["desc2", "setattr(object, "attribute", "the fun things"]}
等
module other
try:
i = int(input())
eval(Config.some_dict[i][1])
except ValueError:
print("nope")
我只是想知道是否有更安全的方法来做到这一点 此外,如果我在程序运行时尝试调试:
try:
eval(input())
except:
pass
这是可接受的还是pythonic还是有更好的方法?我是python的新手(我主要运行JSL所以一切都是用eval(parse())完成的。
答案 0 :(得分:5)
有一种更好的方法:使用一流的功能。
def func2():
setattr(object, "attribute", "the fun things")
some_dict = {
1: ["desc 1", callfunction1],
2: ["desc2", func2]
}
i = int(input())
Config.some_dict[i][1]()
如果您对它们感到满意,可以使用lambda
或partial
减少杂乱。
也就是说,您现有的解决方案并不像eval
的许多用途那么糟糕,因为它不会评估任意用户输入,而是评估硬编码字符串。这显然是不必要的,非常缓慢和丑陋。
对于调试,有专门的调试器。它们比ad-hoc eval-loop工作得更好。
答案 1 :(得分:3)
我建议将字典值变成某种类型的callables。例如,
some_dict = {
1: ["desc 1", callfunction1],
2: ["desc2", lambda: setattr(object, "attribute", "the fun things")]
}
然后,当您想要使用字典中的元素时,只需调用它们:
name, func = some_dict[1]
func()
重要的是字典中的每个值都需要具有相同的调用接口(例如,不带参数)。
答案 2 :(得分:0)
您可以将函数存储为字典中的值,因此只需为每个操作创建一个函数,在字典中查找并调用它。
def set_object_attr(obj=object, name='attribute', value='the fun things'):
setattr(obj, name, value)
some_dict = {1: ["desc 1", callfunction1],
2: ["desc 2", set_object_attr]}
# then wherever you are using this
some_dict[i][1]()
正如您在此处所见,由于callfunction1
已经是一个函数,因此您无需将其包装在另一个调用中。您需要包装setattr()
调用,因为您需要能够在没有任何参数的情况下调用该函数。
我在上面写了set_object_attr
函数,以明确发生了什么,但在这种情况下,最好使用functools.partial
:
import functools
some_dict = {1: ["desc 1", callfunction1],
2: ["desc 2", functools.partial(setattr, object,
'attribute', 'the fun things')]}
答案 3 :(得分:0)
为什么不简单:
some_dict[2]['function'] = setattr
some_dict[2]['options'] = [object, "attribute", "value"]
然后,
if option = 'foo':
some_dict[2]['function'](*some_dict[2]['options'])