我知道不应该使用eval
。出于所有明显的原因(性能,可维护性等)。我的问题更侧重 - 是否有合法用途?应该使用它而不是以另一种方式实现代码。
由于它是以多种语言实现的,并且可能导致糟糕的编程风格,我认为有一个原因使它仍然可用。
答案 0 :(得分:3)
首先,这是Mathwork's list of alternatives to eval。
您也可以聪明并在编译的应用程序中使用eval()
来构建您的mCode解释器,但Matlab编译器出于显而易见的原因不允许这样做。
答案 1 :(得分:2)
我发现合理使用eval
的一个地方是获取我的软件的消费者需要能够作为参数文件的一部分提供的代码的小谓词。
例如,可能有一个名为“Data”的项目具有读取和写入数据的位置,但还需要在加载时应用一些谓词。在Yaml文件中,这可能如下所示:
Data:
Name: CustomerID
ReadLoc: some_server.some_table
WriteLoc: write_server.write_table
Predicate: "lambda x: x[:4]"
在从Yaml加载和解析对象时,我可以使用eval
将谓词字符串转换为可调用的lambda函数。在这种情况下,它意味着CustomerID是一个长字符串,在这个特定的实例中只需要前4个字符。
Yaml提供了一些神奇的方法来神奇地调用对象构造函数(例如在我上面的代码中使用!Data
之类的东西,然后在代码中为Data
定义了一个类,它恰当地使用Yaml钩子进入构造函数)。事实上,我对Yaml魔术对象构造的最大批评之一就是将整个参数文件变成一个巨大的eval
语句。如果你需要验证事物,并且你需要灵活的代码的多个部分吸收参数文件的多个部分,这是非常有问题的。它也不容易用Mako模板化,而我上面的方法很容易。
我认为可以使用任何XML工具轻松解析这个更简单的设计更好,并且使用eval
可以让我允许用户传入他们想要的任意调用。
关于为什么这种情况适用于我的情况的一些注释:
代码的用户不是Python程序员。他们没有能力编写自己的函数,然后只传递模块位置,函数名和参数签名(尽管将所有这些放在参数文件中是解决这个问题的另一种方法,不依赖于{{ 1}} if 可以信任消费者编写代码。)
用户对其糟糕的lambda函数负责。我可以做一些eval
对传递的谓词起作用的验证,甚至可以动态创建一些测试或者有一个很好的失败模式,但是在一天结束时我可以告诉他们这是他们的工作提供有效谓词并确保可以使用简单谓词操作数据。如果没有这个约束,我就不得不把它放在一个不同的系统中。
这些参数文件的用户组成了一个主要愿意遵守约定的小组。如果事实并非如此,那么人们会在谓词领域中做出许多不恰当的事情会很危险 - 而且这很难防范。在大项目上,这不是一个好主意。
我不知道我的观点是否非常适用,但我会说如果你可以保证你的用户是一小组常规持有者,那么使用eval
来增加参数文件的灵活性是很好的。我知道这是一项罕见的壮举。
答案 2 :(得分:2)
在MATLAB中,当函数通过eval
函数使用输入参数的名称时,inputname
函数很有用。例如,要重载内置display
函数(对输入参数的名称敏感),需要eval
函数。例如,要从重载display
调用内置display
,您可以执行
function display(X)
eval([inputname(1), ' = X;']);
eval(['builtin(''display'', ', inputname(1), ');']);
end
在MATLAB中还有evalc
。来自文档:
T = evalc(S)与EVAL(S)相同,除了任何可能的 通常写入命令窗口,错误消息除外 被捕获并返回到字符数组T中(T中的行是 用'\ n'字符分隔。)
如果您仍然考虑这个eval
,那么在处理在命令窗口中显示有用信息的封闭源代码时,它非常强大,您需要捕获并解析该输出。