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
个变量
- 使用
setappdata
and getappdata
我不喜欢用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
我需要类似于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
个变量 - 使用
setappdata
andgetappdata
我不喜欢用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