matlab - 在特定工作空间中访问变量

时间:2015-01-22 05:29:24

标签: matlab recursion workspace

我需要类似evalin的内容,但Matlab的原始evalin不能递归使用。例如,我有函数f0,它调用另外两个函数f11和f12:

function f0()
    [v1, v2] = deal(1, 1);

    f11();
    f12();

    disp(v1);
end

函数f11和f12使用变量v1,并且都调用函数f2:

function f11()
    v1 = evalin('caller', 'v1');

    f2();

    assignin('caller', 'v1', v1);
end

function f12()
    v1 = evalin('caller', 'v1');

    f2();

    assignin('caller', 'v1', v1);
end

函数f2应该使用f0&#39工作空间的变量v1和v2:

function f2()
    v1 = evalin('caller', 'v1');    % get variable v1 from f11 or f12
                                    % since there is already a variable v1 
                                    % in f11 and f12's workspaces
    % TODO: get v2 from f0

    if v2 == 1
        v1 = v1 + 1;
    end

    assignin('caller', 'v1', v1);

end

有没有在f11和f12中不使用v2 = evalin('caller', 'v2')的情况下使TODO成为可能?

3 个答案:

答案 0 :(得分:3)

这可能是在功能之间组织数据传输的最糟糕方式之一。功能的工作区是有充分理由分开的,以保持整洁和有条理。

您正试图绕过设计此语言的人(以及许多其他共享工作空间/范围分离的语言)所实施的所有保护措施。这些“旁路”功能在Matlab中可用,以便在进行原型设计时准时使用。它们不是用于大量使用或最终解决方案(实际上大多数都不可编译)。

  • 可能会让人感到非常困惑(以后再为你,但如果其他人不得不使用你的代码,那就更糟了。)
  • 非常难以调试(您几乎 拥有 以提前知道变量的值,以了解从其他工作区导入是否正确)。

你在评论中说,由于数字的原因,传递变量作为参数是复杂的,但是每当你调用类似x = evalin('caller', 'x');之类的东西时,你必须编写1行完整的代码来检索你的价值。然后assignin('caller', 'x', x);是另一行代码发送回来......那很疯狂。

在函数输入参数中只有x会不会更简单(也更短)? (在输入中有100个变量比要检索200个完整的代码行然后从不确定的位置重新发送这些值更快。)


推荐(如果可行):在参数

中传递变量

为了让变量传递变得简单,您可以将它们全部收集到structure(或cell array)中:

[v1, v2] = deal(1, 1);
myVars.v1 = v1 ;
myVars.v2 = v2 ;

myVars = f11(myVars); %// you only have one variable to pass into your functions
myVars = f12(myVars); %// just make sure you retrieve it in output too

disp(myVars.v1);

然后

function myVars = f11()
    myVars = f2(myVars);
end

依此类推,只要你将变量传递给下一个函数,然后在输出中检索它,这将适用于任何级别的递归。


推荐(如果不可能):使用嵌套函数

如果您在f11()内定义<{1}} 中的函数,则会共享2个函数中具有相同名称的变量(在两个层面都可见)。请阅读documentation了解更多详情。通过这种方式,您不需要多次调用f0(),因为变量随处可见。您的功能必须以这种形式编写:

evalin/assignin

Stack Exchange不会渲染它,但是在Matlab编辑器中你可以注意到“共享”变量将以不同的颜色突出显示(提醒你它们的范围与标准变量不同)。

如果我运行function f0() [v1, v2] = deal(1, 1); f11(); f12(); disp(v1); function f11() f2(); function f2() if v2 == 1 v1 = v1 + 1; end end end %// END function F11 function f12() f2(); function f2() if v2 == 1 v1 = v1 + 1; end end end %// END function F12 end %// END function F0 ,我会得到:

f0()

这是预期的结果。正如您所看到的,唯一的缺点是,如果您从>> f0 3 f2()内拨打f11(),则必须在每个内容中编写f12()函数(所以有点复制/粘贴)。除非在这种递归级别,你没有太多的变量要传递,所以你可以考虑在侧面编写f2()并使用标准变量传递方案。


可以工作,但不推荐

现在,如果您仍然热衷于编写多行代码来传递单个变量,那么仍然有两个选项:

我不想使用f2()所以我不会在这里详述。请记住,要使变量真正global,必须在 每个 函数中将其声明为global

对于global方法,您需要一个可以访问所有功能的“容器”。您可以使用“root”对象(标识符: appdata)。

因此,例如,当您想要存储可以使用的变量时:

0

然后在你的任何函数中,获取值,处理它然后将其存储回来:

setappdata( 0 , 'v2' , v2 ) %// store the value of `v2` in a field named `'v2'` in the root object.

在基本函数和function f2() v1 = getappdata(0,'v1') %// get the value of v1 v2 = getappdata(0,'v2') %// get the value of v2 if v2 == 1 v1 = v1 + 1; %// modify the value of v1 end v1 = setappdata(0,'v1',v1) %// store the value of v1 end f11()等中应用相同的原则...只需记住在修改它之后总是存储任何值,以便它可用于下一个函数需要它。

答案 1 :(得分:1)

试图做到这一点:你的变量&#39;持有一个值,该值应该与您希望对它们执行的操作保持一致。只是在黑暗中拍摄,但你在问题上尝试了面向对象。

classdef myObj
properties
    v1;
    v2;
end
methods
    function f1(obj)
        ... do something here ....
        obj.v1 = ....;
    end
    function f2(obj)
        obj.f1();
    end
end

根据您的具体问题,这可能是获得正确递归的最简单方法。 OO in Matlab isnt that hard to learn

H个

答案 2 :(得分:0)

您可以将f0()个变量保存到文件中,然后调用load中的f2()方法将这些变量导入f2()工作区。