matlab - 访问特定工作区中的变量

matlab - access variable in specific 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 工作区的变量 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 成为可能?

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

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

您正试图绕过设计此语言(以及共享 workspace/scope 这种分离的许多其他语言)的人员设置的所有保护措施。这些 "bypass" 函数在 Matlab 中可用,可在您制作原型时准时使用。它们不适用于大量使用或最终解决方案(其中大多数实际上无法编译)。

  • 可能会非常混乱(稍后对您来说,但如果其他人必须使用您的代码,情况会更糟)。
  • 很难调试(你几乎提前知道变量的值知道是否从另一个工作区导入是对的)。

你在评论中说,由于变量的数量,将变量作为参数传递很复杂,但每次你调用 x = evalin('caller', 'x'); 之类的东西时,你都必须编写一整行代码来检索你的值。然后 assignin('caller', 'x', x); 是另一行代码将其发回......这太疯狂了。

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


推荐(如果可行):在参数中传递变量

为了使变量传递更容易,例如你可以将它们全部收集在一个 structure (or a 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()里面定义你的函数你的f0(),变量有相同的名字在 2 个函数中将共享(在两个级别可见)。阅读 documentation 了解更多详情。这样你就不需要多次调用 evalin/assignin 因为变量随处可见。您的函数必须以这种形式编写:

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

Stack Exchange 不会呈现它,但在 Matlab 编辑器中,您会注意到 "shared" 变量将以不同的颜色突出显示(以提醒您它们的作用域与标准变量不同)。

如果我 运行 f0() 我得到:

>> f0
     3

这是预期的结果。如您所见,唯一的缺点是,如果您从 f11()f12() 中调用 f2(),则函数 f2() 必须写入它们中的每一个(所以有点 copy/paste)。除非在这个递归级别你没有太多的变量要传递,所以你可以考虑在旁边写 f2() 并使用标准变量传递方案。


可以,但不推荐

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

我不喜欢用global所以这里就不细说了。请记住,对于真正的 global 变量,它必须在 every 函数中声明为 global被使用了。

对于 appdata 方法,您需要一个 "container",您的所有函数都可以访问它。您可以为此使用 "root" 对象 (identifier: 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()f12() 等中应用相同的原则...只要记住在修改后始终将任何值存储回去,以便下一个函数可用这将需要它。

只是想做对:您的 'Variables' 持有的值应该与您希望对它们执行的操作保持一致。只是在黑暗中拍摄,但您是否尝试过面向对象解决您的问题。

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

Hth