在工作区之间共享数据
简介
本主题介绍如何在工作区之间共享变量或如何使它们在函数执行之间持久保留。
大多数情况下,在函数内创建的变量是仅可在该函数内识别的局部变量。局部变量不能用在命令行中,也不适用于任何其他函数。但是,可以通过多种方式在函数或工作区之间共享数据。
最佳做法:传递参数
扩大函数变量作用域的最安全的方式是使用函数输入和输出参数,这样您可以传递变量的值。
例如,创建两个函数 update1
和 update2
,它们共享和修改输入值。update2
可以是文件 update1.m
中的局部函数,也可以是它自己的文件 update2.m
中的函数。
function y1 = update1(x1) y1 = 1 + update2(x1); function y2 = update2(x2) y2 = 2 * x2;
从命令行调用 update1
函数并向基础工作区中的变量 Y
赋值:
X = [1,2,3]; Y = update1(X)
Y = 3 5 7
嵌套函数
嵌套函数可以访问其所在的所有函数的工作区。所以,例如嵌套函数可以使用在其父函数中定义的变量(在本例中为 x
):
function primaryFx x = 1; nestedFx function nestedFx x = x + 1; end end
如果父函数不使用指定变量,变量保持为嵌套函数的局部变量。例如,在该版本的 primaryFx
中,以下两个嵌套函数拥有它们自己的不能彼此交互的 x
版本。
function primaryFx nestedFx1 nestedFx2 function nestedFx1 x = 1; end function nestedFx2 x = 2; end end
有关详细信息,请参阅嵌套函数。
持久变量
如果将函数内的变量声明为持久变量,则从一个函数调用转到下个函数调用时变量会保留其值。其他局部变量仅在当前函数执行期间保留它们的值。持久变量等效于其他编程语言中的静态变量。
要使用 persistent
关键字声明变量之后再使用它们。MATLAB® 将持久变量初始化为空矩阵 []
。
例如,在名为 findSum.m
的文件中定义一个函数,先将总和值初始化为 0
,然后在每次迭代时与该值相加。
function findSum(inputvalue) persistent SUM_X if isempty(SUM_X) SUM_X = 0; end SUM_X = SUM_X + inputvalue;
调用该函数时,SUM_X
的值在后续执行之间持久保留。
以下操作可清除函数的持久变量:
clear all
clear
functionname
编辑函数文件
要避免清除持久变量,请使用 mlock
锁定函数文件。
全局变量
全局变量是您可以从函数或命令行中访问的变量。它们拥有自己的工作区,这些工作区与基础和函数工作区分开。
但是,全局变量具有显著风险。例如:
任何函数都可以访问和更新全局变量。使用此类变量的其他函数可能返回意外结果。
如果您无意间提供与现有全局变量同名的“新”全局变量,一个函数可能覆盖另一个函数预期的值。此类错误很难诊断。
请尽可能谨慎使用全局变量。
如果您使用全局变量,请使用 global
关键字声明它们,然后从任何特定位置(函数或命令行)访问它们。例如,在名为 falling.m
的文件中创建一个函数:
function h = falling(t) global GRAVITY h = 1/2*GRAVITY*t.^2;
然后在提示符下输入这些命令:
global GRAVITY
GRAVITY = 32;
y = falling((0:.1:5)');
通过上述两条全局语句,可以在函数内使用在命令提示符下赋值给 GRAVITY
的值。但是,更为稳健的做法是,重新定义函数以接该值作为输入:
function h = falling(t,gravity)
h = 1/2*gravity*t.^2;
然后在提示符下输入这些命令:
GRAVITY = 32; y = falling((0:.1:5)',GRAVITY);
在另一工作区中计算
通过 evalin
和 assignin
函数,您可以计算字符向量中的命令或变量名称并指定是否使用当前或基础工作区。
和全局变量一样,这些函数存在覆盖现有数据的风险。请谨慎使用它们。
evalin
和 assignin
有时可用于图形用户界面中的回调函数,以针对基础工作区计算。例如,从基础工作区创建变量名称的列表框:
function listBox figure lb = uicontrol('Style','listbox','Position',[10 10 100 100],... 'Callback',@update_listBox); update_listBox(lb) function update_listBox(src,~) vars = evalin('base','who'); src.String = vars;
对于其他编程应用程序,考虑使用eval 函数的替代方法中介绍的参数传递和方法。