【问题标题】:MATLAB: script vs function concerning output-argumentMATLAB:关于输出参数的脚本与函数
【发布时间】:2013-11-29 09:03:56
【问题描述】:

我有一个脚本可能由于运行时间过长而中止并稍后继续。让我们假设它看起来有点像这样:

data = []; % can't preallocate as I don't know the number of entries yet here...
while(1)
   % ...
   data = [data; someNewEntry];
end

它的好处是,当作为脚本运行时,每当我中止它时,我的工作区中有变量 data

但我想将它转换成一个函数,因为该脚本包含大量变量,并且用它弄乱了我的工作空间。假设我现在这样转换它:

function data = myFnc()
data = []; % can't preallocate as I don't know the number of entries yet here...
while(1)
   % ...
   data = [data; someNewEntry];
end

现在的问题是:当我中止函数时,我将丢失 data 中的所有条目。如何解决这个问题并在中止函数时返回当前向量data?我想出的唯一可能的解决方案是在 for 循环中使用这样的东西:

if(nargout == 1)
   assignin('caller','data', data);
end

但不知何故,我不太喜欢这种方法。但好吧,我觉得没问题。但是有一件事仍然让我烦恼:使用它时,我总是将数据分配给工作区变量data,因为我不知道如何获取调用者的输出变量的名称(即bla = myFnc() ->它将是bla,因此是assignin('caller','bla', data);)。我知道有 matlab 函数 inputnames() 但我找不到输出变量的等效函数。 提前非常感谢!

【问题讨论】:

  • 旁注,例如,如果 someNewEntry 是一个标量。您可以通过以下方式更有效地发展datadata(end+1) = someNewEntry
  • 谢谢你,但它实际上是一个构建数据矩阵的向量 :) 但还是很高兴知道
  • 在这种情况下,它将是data(end+1,:) = someNewEntry
  • 哦不知道这样更快,谢谢!

标签: matlab function return-value workspace


【解决方案1】:

我能想到 2 个推荐的解决方案:

1.在不丢失工作空间的情况下中断函数

正如我所描述的here,如果你总是打开这应该不是问题

`dbstop if error`

2。经常保存变量

使用您的分配解决方案,您已经接近,因为它将变量“保存”到基础工作区。然而,这仍然不是一个非常安全的存储变量的空间。因此,我建议将它们保存为:

save data data

如果第二个选项对性能的影响太大,您可以每 1000 次左右迭代一次。

【讨论】:

  • 我也在脚本末尾将它保存到一个文件中:-) 但是我明白你关于保存的观点。你知道获取调用者输出变量名称的方法吗?
  • 有一个函数可以为您提供调用者输入变量的名称 (mathworks.co.uk/help/matlab/ref/inputname.html),但我似乎找不到输出变量的等效项。
【解决方案2】:

一种解决方案可能是使用全局变量。一个简单计数器的例子:

function data = myFnc()

global data; % make it a global
if isempty(data) % not yet initialized
    data = [];
end

i = 1;
while(i < 10)
   pause(1)
   disp(i)
   data = [data, i];
   i = i + 1;
end

然后在命令行,你必须做一次global data,你就可以访问保存的状态。快速测试,我在运行时用 CTRL+C 中止了程序:

>> clear
>> clear global
>> x = myFnc();
     1
     2
     3
     4
Operation terminated by user during myFnc (line 10)
>> x
Undefined function or variable 'x'.
>> data
Undefined function or variable 'data'.
>> global data
>> data
data =
     1     2     3     4

通常不建议使用全局变量,但有时它们会很有用。我有时会使用全局变量来缓存昂贵的计算,这样每次启动 Matlab 时它只需要计算一次:

global data;
if isempty(data)
    data = expensive_calculation();
end

对于复杂的程序,可能有更简洁的方法将一些状态从一个迭代保存到另一个迭代(实现某个对象?,将一个状态对象从一个迭代传递到下一个迭代?,保存到文件?),但对于一些快速和脏脚本,使用全局变量可能是最简单的方法。

【讨论】:

  • 唯一的事情是:您也在写入名为 data 的变量,而不是动态写入命名为调用者命名它的变量 :-) 这将是一件好事.但是好的,至少全局数据变量不会自动覆盖可能已经存在于工作区中的变量data(就像使用assignin() 时一样)。所以这也是一个很酷的方法:)
  • @bjoern 是的,最好给全局变量一个不同的名称,以避免覆盖现有变量。
【解决方案3】:

另一种选择是使用 MATLAB 引用类型变量。例如,您可以使用containers.Map,如下所示:

m = containers.Map();
myFcn(m);
% Later, after hitting CTRL-C
m('data') % get latest value

使用这样的功能:

function myFcn(map)
data = [];
while true
    data = [data, rand()];
    map('data') = data;
end

【讨论】:

    猜你喜欢
    • 2017-10-10
    • 2017-02-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-26
    相关资源
    最近更新 更多