一个简单的实现是用
eval替换
str2func,这样你就不会遇到str2func不允许访问局部变量的障碍.我们可以使用
functions获取输入函数句柄的工作空间信息.
例如:
a = 5;
f = @(x) x+a;
finfo = functions(f)
产量:
finfo =
struct with fields:
function: '@(x)x+a'
type: 'anonymous'
file: 'X:\testcode-matlab\testcode.m'
workspace: {[1×1 struct]}
within_file_path: 'testcode'
工作空间是包含结构(来自MathWorks …)的单元格数组,其中包含函数句柄命名空间中的所有变量:
>> wspace = finfo.workspace{1}
wspace =
struct with fields:
a: 5
使用此功能,天真的解决方案是遍历此工作空间中的变量,在更改函数的命名空间中分配它们,然后使用eval生成新的函数句柄.
例如:
function f2 = changefunction_new(f1)
tmp = functions(f1);
workspacevars = tmp.workspace{1};
varnames = fieldnames(workspacevars);
for ii = 1:length(varnames)
evalstr = sprintf('%s = %d;', varnames{ii}, workspacevars.(varnames{ii}));
eval(evalstr);
end
fs = func2str(f1);
fs(fs=='+') = '*';
f2 = eval(fs);
end
在这里,我假设变量将是严格的数字.如果情况并非总是如此,您可以添加逻辑来检查要生成的数据类.
有了这个,我们有:
a = 5;
g = @(x) x+a;
test1 = changefunction(g);
test2 = changefunction_new(g);
>> g(1)
ans =
6
>> test1(1)
Undefined function or variable 'a'.
Error in testcode>@(x)x*a
>> test2(1)
ans =
5
总而言之,最好的解决方案就是明确定义你的函数句柄.这可能是一种痛苦,但它更容易理解和调试.
一些警告:
>因为eval任意执行传递给它的所有代码,所以必须小心使用它才是一个非常危险的函数.
>函数文档警告不要以编程方式使用它,因此在MATLAB版本更改时请注意检查行为:
Use the functions function for querying and debugging purposes only.
Note: Do not use functions programmatically because its behavior could change in subsequent MATLAB® releases.