11.4 多个返回值

与许多其他计算机语言不同,Octave允许您定义返回多个值的函数。定义返回多个值的函数的语法如下:

function [ret-list] = name (arg-list)
  body
endfunction

其中namearg-listbody的含义与之前相同,而ret-list是一个以逗号分隔的变量名列表,用于存放函数返回的值。返回值列表必须至少包含一个元素。如果ret-list只有一个元素,则这种形式的function语句与上一节中描述的形式等价。

下面是一个函数示例,它返回两个值:向量的最大值以及该值在向量中首次出现的索引。

function [max, idx] = vmax (v)
  idx = 1;
  max = v (idx);
  for i = 2:length (v)
    if (v (i) > max)
      max = v (i);
      idx = i;
    endif
  endfor
endfunction

在这个特定例子中,这两个值可以作为单个数组的元素返回,但这并不总是可行或方便的。需要返回的值可能不具有兼容的维度,而且通常希望为各个返回值赋予不同的名称。

可以使用nthargout函数来只获取部分返回值,或一次性在元胞数组中获取多个返回值。 参见元胞数组对象

 
arg = nthargout (n, fcn, …)
arg = nthargout (n, ntot, fcn, …)

返回由函数句柄或字符串fcn所指定函数的第n个输出参数。

任何额外的参数都会直接传递给fcn。可以通过ntot传入调用fcn时使用的参数总数;默认情况下ntot等于n。输入参数n也可以是一个输出索引的向量,此时输出将是一个包含所请求输出参数的元胞数组。

nthargout的预期用途是避免使用中间变量。例如,在查找矩阵最大元素的索引时,以下两个nthargout的组合使用

m = magic (5);
cell2mat (nthargout ([1, 2], @ind2sub, size (m),
                     nthargout (2, @max, m(:))))
⇒  5   3

完全等价于以下代码:

m = magic (5);
[~, idx] = max (M(:));
[i, j] = ind2sub (size (m), idx);
[i, j]
⇒  5   3

如下代码所示,将所有输出参数收集到单个元胞数组中也很有帮助:

USV = nthargout ([1:3], @svd, hilb (5));

编程提示:nthargout函数的等效功能通常可以通过在代码中使用字符‘~’来忽略输出来实现。此功能由Octave解释器提供,且比使用本函数更高效。

等效代码:

idx = nthargout (2, @max, rand (100, 1));
≡
[~, idx] = max (rand (100, 1));

另请参阅: narginnargoutvararginvarargoutisargout

除了在每次调用函数时设置nargin之外,Octave还会自动将nargout初始化为期望返回的值的数量。这允许您编写根据函数用户请求的返回值数量而表现不同的函数。对内置变量ans的隐式赋值不计入输出参数的计数,因此nargout的值可能为零。

svdhist函数就是根据nargout的值表现不同的内置函数示例。例如,hist在没有输出变量的情况下调用时会绘制直方图,但如果调用时指定了输出,则它会返回频率计数和/或组边界,而不会创建图形。

可以编写只设置部分返回值的函数。例如,调用函数

function [x, y, z] = f ()
  x = 1;
  z = 2;
endfunction

如下所示:

[a, b, c] = f ()

会得到:

a = 1

b = [](0x0)

c = 2

同时会显示一条警告。

 
n = nargout ()
n = nargout (fcn)

报告函数的输出参数数量。

在函数内部调用时,返回调用者期望接收的值的个数。在顶层调用时,不带参数的nargout未定义,会产生错误。

如果使用可选参数fcn(函数名或句柄)调用,则返回该函数可以产生的已声明的输出值个数。

如果最后一个输出参数是varargout,则返回值为负数。

例如,

f ()

将使nargout在函数f内部返回0,而

[s, t] = f ()

将使nargout在函数f内部返回2。

在第二种用法中,

nargout (@histc)   # 或使用字符串输入 nargout ("histc")

将返回2,因为histc有两个输出,而

nargout (@imread)

将返回-2,因为imread有两个输出,且第二个是varargout

编程提示:nargout不适用于内置函数,对于所有匿名函数返回-1。

另请参阅: narginvarargoutisargoutnthargout


版权所有 © 2024-2026 Octave中文网

ICP备案/许可证号:黑ICP备2024030411号-2