1

我总是厌倦在任何语言中使用 eval 但我想不出更好的方法来做两件事。从我读过的所有内容来看,evAl 都是邪恶的(这很糟糕)。任何想法表示赞赏。我有一个带有字典的模块,该字典可以调用函数或设置属性,具体取决于您从另一个模块调用它的方式

module Config
some_dict = {1: ["desc 1", "callfunction1()"], 
  2: ["desc2", "setattr(object, "attribute", "the fun things"]} 

ETC

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()) 完成的。

4

4 回答 4

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,因为它不评估任意用户输入,而是评估硬编码字符串。这完全是不必要的,非常缓慢且丑陋。

对于调试,有专门的调试器。它们比临时评估循环工作得更好。

于 2013-08-09T16:19:17.297 回答
3

我建议将您的字典值转换为某种可调用对象。例如,

some_dict = {
    1: ["desc 1", callfunction1], 
    2: ["desc2", lambda: setattr(object, "attribute", "the fun things")]
}

然后,当您想使用字典中的元素时,只需调用它们:

name, func = some_dict[1]
func()

重要的是字典中的每个值都需要具有相同的调用接口(例如,不带参数)。

于 2013-08-09T16:20:02.663 回答
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')]}
于 2013-08-09T16:18:51.653 回答
0

为什么不简单:

some_dict[2]['function'] = setattr
some_dict[2]['options'] = [object, "attribute", "value"]

然后,

if option = 'foo':
   some_dict[2]['function'](*some_dict[2]['options'])
于 2013-08-09T16:19:26.247 回答