eval 函数的替代方法
为什么要避免使用 eval 函数?
虽然 eval
函数非常强大和灵活,但它并不总是编程问题的最佳解决方案。与使用其他函数或语言构造的代码相比,调用 eval
的代码通常效率较低,而且难以阅读和调试。例如:
MATLAB® 会在您首次运行代码时对代码进行编译,以增强以后运行的性能。但是,由于
eval
语句中的代码可在运行时更改,因此无法进行编译。eval
语句中的代码可能会意外创建变量或为当前工作区中已存在的变量赋值,并覆盖现有的数据。eval
语句中的串联字符向量通常难以阅读。其他语言构造方式可以简化您代码中的语法。
对于 eval
的许多常见用法,有一些首选的替代方法,下面以示例形式介绍了这些方法。
带有序列名称的变量
eval
函数的常见用法是创建 A1
、A2
、...
、An
之类的变量集,但此方法不使用 MATLAB 的数组处理功能,因此建议不要使用。首选方法是将相关数据存储在单个数组中。如果数据集具有不同的类型或大小,请使用结构体或元胞数组。
例如,创建一个包含 10 个元素的元胞数组,其中每个元素都是数值数组:
numArrays = 10; A = cell(numArrays,1); for n = 1:numArrays A{n} = magic(n); end
通过花括号创建索引来访问元胞数组中的数据。例如,显示 A
的第五个元素:
A{5}
ans = 17 24 1 8 15 23 5 7 14 16 4 6 13 20 22 10 12 19 21 3 11 18 25 2 9
赋值语句 A{n} = magic(n)
要比下面调用 eval
的语法更为简洁高效:
eval(['A', int2str(n),' = magic(n)']) % Not recommended
有关详细信息,请参阅:
带有序列名称的文件
相互关联的数据文件通常具有一个共同的带整数索引的根名称,例如 myfile1.mat
到 myfileN.mat
。eval
函数的一个常见(但不建议)用法是使用命令语法构造每个文件名并将它们传递给某个函数,例如
eval(['save myfile',int2str(n),'.mat']) % Not recommended
最佳做法是使用函数语法,该语法允许您将变量作为输入传递。例如:
currentFile = 'myfile1.mat';
save(currentFile)
您可以使用 sprintf
函数(通常比 int2str
更有效)在循环内构造文件名,然后调用 save
函数,而无需使用 eval
。此代码在当前文件夹中创建 10 个文件:
numFiles = 10; for n = 1:numFiles randomData = rand(n); currentFile = sprintf('myfile%d.mat',n); save(currentFile,'randomData') end
有关详细信息,请参阅:
变量中的函数名称
eval
的一个常见用法是当函数的名称位于可变字符向量中时执行函数。有两种方式可计算变量中的函数,每一种都比使用 eval
更为高效:
使用
@
符号或使用str2func
函数创建函数句柄。例如,从元胞数组中存储的列表运行函数:examples = {@odedemo,@sunspots,@fitdemo}; n = input('Select an example (1, 2, or 3): '); examples{n}()
使用
feval
函数。例如,使用您在运行时指定的数据调用绘图函数(例如plot
、bar
或pie
):plotFunction = input('Specify a plotting function: ','s'); data = input('Enter data to plot: '); feval(plotFunction,data)
变量中的字段名称
通过将字段表达式括入括号中,使用变量字段名称访问结构体中的数据。例如:
myData.height = [67, 72, 58]; myData.weight = [140, 205, 90]; fieldName = input('Select data (height or weight): ','s'); dataToUse = myData.(fieldName);
如果您在输入提示符处输入 weight
,则可以使用以下命令查找最小 weight
值。
min(dataToUse)
ans = 90
有关其他示例,请参阅基于变量生成字段名称。
错误的处理方式
MATLAB 中处理错误的首选方法是使用 try, catch
语句。例如:
try B = A; catch exception disp('A is undefined') end
如果您的工作区不包含变量 A
,则该代码返回:
A is undefined
eval
函数以前版本的文档中包含 eval(expression,catch_expr)
语法介绍。如果计算 expression
输入返回错误,则 eval
会计算 catch_expr
。但是,在 eval
语句中,显式的 try/catch
明显比隐式的 catch 更清晰。建议不要使用隐式的 catch。