Matlab 是否可以更改保留工作区的匿名函数?
我希望能够以编程方式更改匿名函数,例如,将函数中的所有加号更改为乘法符号。此示例在许多情况下都可以按如下方式执行:Matlab 是否可以更改保留工作区的匿名函数?,matlab,anonymous-function,Matlab,Anonymous Function,我希望能够以编程方式更改匿名函数,例如,将函数中的所有加号更改为乘法符号。此示例在许多情况下都可以按如下方式执行: function f2 = changefunction(f1) fs = func2str(f1); fs(fs=='+') = '*'; f2 = str2func(fs); end 但是考虑例子 f = @(x) x+5; a = 5; g = @(x) x+a; f和g都是匿名函数,在插入的任何内容中添加5;但是,只有f会被changefunct
function f2 = changefunction(f1)
fs = func2str(f1);
fs(fs=='+') = '*';
f2 = str2func(fs);
end
但是考虑例子
f = @(x) x+5;
a = 5;
g = @(x) x+a;
f
和g
都是匿名函数,在插入的任何内容中添加5;但是,只有f
会被changefunction
功能正确更改,而g
会被更改为任何输入都会出错的功能
所以我的问题是,是否可以从函数句柄中提取工作空间,并将其保留在创建的新函数句柄中?我需要以编程方式完成,最好不要使用内置函数
函数 一个简单的实现是替换为,这样您就不会遇到str2func
不允许访问局部变量的障碍。我们可以使用获取输入函数句柄的工作空间信息
例如:
a = 5;
f = @(x) x+a;
finfo = functions(f)
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
收益率:
finfo =
struct with fields:
function: '@(x)x+a'
type: 'anonymous'
file: 'X:\testcode-matlab\testcode.m'
workspace: {[1×1 struct]}
within_file_path: 'testcode'
其中workspace
是一个单元格数组,其中包含一个结构(come on MathWorks…),该结构包含函数句柄命名空间中的所有变量:
>> wspace = finfo.workspace{1}
wspace =
struct with fields:
a: 5
使用此功能,最简单的解决方案是循环此工作区中的变量,在changefunction
的命名空间中分配它们,然后使用eval
生成新的函数句柄
例如:
a = 5;
f = @(x) x+a;
finfo = functions(f)
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版本更改时的行为:
使用函数
函数仅用于查询和调试目的
注意:不要以编程方式使用函数,因为其行为可能会在后续的MATLAB®版本中发生变化
一种可能的方法是将函数句柄保存到.mat
文件中(使用-v7.3
标志,以便创建易于修改的HDF5文件),修改包含匿名函数工作空间数据的文件中的结构(使用MATLAB内置的HDF5工具),然后从文件中再次加载匿名函数
这里有一个小函数,它正好做到这一点(它适用于相对简单的变量类型)
你可以像这样使用它:
a = 1;
b = struct('field', 2);
f = @(x)disp(a + b.field + x);
f(10)
% 13
f2 = modifyfunc(f, 'a', 2);
f2(10)
% 14
f3 = modifyfunc(f2, 'b.field', 3);
f3(10)
% 15
b.field = 4;
f4 = modifyfunc(f3, 'b', b);
f4(10)
% 16
一些警告包括:
- 替换数据必须与原始数据大小相同
- 这依赖于.mat文件的格式,对于匿名函数,该文件完全没有文档记录,因此在将来的版本中可能会失败
- 这目前不适用于函数工作区中
cell
数组的变量
为了获得轻微的额外安全余量,您可以将其重新加载。它仍然很脏,仍然使用函数。