MATLAB匿名函数固定参数未更新:是预期行为还是Bug?如何解决?
解答:MATLAB匿名函数中外部变量不更新的问题
你遇到的这个情况完全是MATLAB的预期行为,并不是Bug!咱们来一步步拆解原因和解决办法:
为什么修改var2后,匿名函数里的值没变化?
MATLAB的匿名函数在创建时,会把它用到的外部变量(比如这里的var2和nhi)的当前值直接“快照”嵌入到函数定义里,而不是保存对这些工作区变量的引用。也就是说,当你写下objFun = @(var1) objFunModel(var1, var2, nhi);的瞬间,MATLAB就把当时var2和nhi的具体数值存在了匿名函数内部,后续你在外部修改这两个变量,已经创建好的匿名函数完全不会感知到——它只会用创建时捕获的那个旧值。
你可以试试在命令行输入functions(objFun),查看匿名函数的捕获变量详情,就能看到它保存的是创建时的var2值,而不是指向工作区变量的链接。
怎么让匿名函数使用更新后的var2?
这里有几种实用的解决方式,你可以根据自己的使用场景选择:
方法1:重新定义匿名函数(最直接的方案)
每次修改var2之后,重新创建一次匿名函数,这样它就会捕获最新的var2值:
% 修改var2的代码 var2 = zeros(hoursTotal, 1); var2(4:4:end) = 1; % 重新定义匿名函数,绑定最新的var2 objFun = @(var1) objFunModel(var1, var2, nhi); % 现在调用就会用新的var2了 objFun(var1_initial);
方法2:把var2作为匿名函数的输入参数
如果var2需要频繁修改,不如直接把它加到匿名函数的输入列表里,这样每次调用时都能传入最新的值:
% 重新定义匿名函数,把var2设为参数 objFun = @(var1, var2) objFunModel(var1, var2, nhi); % 第一次调用,传入初始的var2 objFun(var1_initial, var2); % 修改var2后,调用时传入新值即可 var2 = zeros(hoursTotal, 1); var2(4:4:end) = 1; objFun(var1_initial, var2);
方法3:用句柄类包装var2(适合频繁更新且不想重复定义函数的场景)
MATLAB的句柄类是按引用传递的,把var2放到一个句柄类实例里,匿名函数捕获这个实例后,后续修改实例里的var2,匿名函数就能直接拿到最新值:
首先定义一个简单的句柄类(可以单独存成.m文件,或者写在脚本开头):
classdef DataHolder < handle properties value end end
然后在你的主代码里这样用:
% 用句柄类包装var2 var2_holder = DataHolder(); var2_holder.value = zeros(hoursTotal, 1); var2_holder.value(2:2:end) = 1; % 定义匿名函数时捕获这个句柄实例 objFun = @(var1) objFunModel(var1, var2_holder.value, nhi); % 第一次调用,用初始的var2 objFun(var1_initial); % 此时sum(var2) = 36 % 修改句柄实例里的value var2_holder.value = zeros(hoursTotal, 1); var2_holder.value(4:4:end) = 1; % 再次调用,自动使用更新后的var2 objFun(var1_initial); % 此时sum(var2) = 18
总结
- 匿名函数对外部变量的捕获是值绑定,而非引用绑定,这是MATLAB的设计逻辑;
- 最简便的解决方式是每次修改变量后重新定义匿名函数;
- 如果变量需要频繁更新,推荐把它设为匿名函数的输入参数,或者用句柄类实现引用式的动态更新。
内容的提问来源于stack exchange,提问作者winkmal
相关产品推荐
相关产品推荐

