是否可以更改保持工作空间的匿名功能?

Jen*_*sen 3 matlab anonymous-function

我希望能够以编程方式更改匿名函数,例如通过将所有加号更改为函数中的乘法符号.在许多情况下,此示例可以按如下方式完成:

function f2 = changefunction(f1)
    fs = func2str(f1);
    fs(fs=='+') = '*';
    f2 = str2func(fs);
end
Run Code Online (Sandbox Code Playgroud)

但请考虑这个例子

f = @(x) x+5;
a = 5;
g = @(x) x+a;
Run Code Online (Sandbox Code Playgroud)

双方fg会匿名函数,增加了5,无论你塞了进去; 但是只有功能f才能正确更改changefunction,而g将被更改为任何输入都会出错的功能.

所以我的问题是是否可以从函数句柄中提取工作区并将其保留在创建的新函数句柄中?我需要以编程方式进行,最好不使用内置函数functions!

exc*_*aza 5

一个简单的实现是替换为str2func,eval所以你没有遇到str2func不允许访问局部变量的障碍.我们可以functions用来获取输入函数句柄的工作空间信息.

例如:

a = 5;
f = @(x) x+a;
finfo = functions(f)
Run Code Online (Sandbox Code Playgroud)

产量:

finfo = 

  struct with fields:

            function: '@(x)x+a'
                type: 'anonymous'
                file: 'X:\testcode-matlab\testcode.m'
           workspace: {[1×1 struct]}
    within_file_path: 'testcode'
Run Code Online (Sandbox Code Playgroud)

workspace包含结构(来自MathWorks ...)的单元格数组在哪里,其中包含函数句柄命名空间中的所有变量:

>> wspace = finfo.workspace{1}

wspace = 

  struct with fields:

    a: 5
Run Code Online (Sandbox Code Playgroud)

使用此功能,天真的解决方案是循环遍历此工作空间中的变量,在命名空间中分配它们changefunction,然后用于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
Run Code Online (Sandbox Code Playgroud)

在这里,我假设变量将是严格的数字.如果情况并非总是如此,您可以添加逻辑来检查要生成的数据类.

有了这个,我们有:

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
Run Code Online (Sandbox Code Playgroud)

总而言之,最好的解决方案就是明确定义你的函数句柄.这可能是一种痛苦,但它更容易理解和调试.


一些警告:

  • 因为eval任意执行传递给它的所有代码,所以必须谨慎使用它是一个非常危险的函数.
  • functions警告文档不要以编程方式使用它,因此在MATLAB版本更改时请注意检查行为:

使用该functions功能仅用于查询和调试目的.

注意:不要以编程方式使用函数,因为它的行为可能会在后续的MATLAB®版本中发生变化.

  • 为了获得额外的安全保证,你可以*[将结构字段保存为mat文件中的单独变量](https://www.mathworks.com/help/matlab/matlab_env/save-load-and-delete-workspace -variables.html#bvdx_92-1)并重新加载它.它仍然很脏,但仍然使用`functions`. (2认同)