Arguments_in_Matlab中的函数参数
函数参数
当我们定义函数时,我们可以使用如下的语法形式。当然Matlab中,并没有参数类型标识的语法,所以这里的x1,…,xM只是一个形式,实际上可以是任何类型的参数。
1function [y1,...,yN] = myfun(x1,...,xM)
古早时期,我学Matlab的时候,通常会在函数中调用如下几个函数来进行处理,判断函数的类型、验证函数参数的有效性、实现函数的多态性。
- nargin
- nargout
- varargin
在2019b版本之后,Matlab引入了新的函数参数处理语法arguments...end
,这个方式更加直观,也更加方便。
1function [y1,...,yN] = myfun(x1,...,xM)
2 arguments
3 x1 (1,1) double
4 x2 (1,1) double
5 ...
6 xM (1,1) double
7 end
8
9 % 函数体
10end
这个语法已经有四种形式,分别是:
- 输入参数
- 重复输入参数
- 输出参数
- 重复输出参数
输入参数
对于输入参数,我们可以使用如下的语法形式。
1arguments
2 argName1 (dimensions) class {validators} = defaultValue
3 ...
4 argNameN ...
5end
这里,argName是参数的名字,dimensions是参数的维度,class是参数的类型,validators是参数的验证函数,defaultValue是参数的默认值。
- argName:形式参数的名字,可以是任意合法的变量名,必须出现在函数的定义中。
- dimensions:形式参数的维度,至少要一个维度,
(1,1)
表示标量,(1,:)
表示行向量,(:,1)
表示列向量,(:,:)
表示矩阵,只能是常量。 - class:形式参数的类型,可以是任意合法的类型,如
double
、char
、string
、logical
、cell
、struct
、table
、function_handle
等。 - validators:形式参数的验证函数集合(元胞数组),函数名称,用于验证参数的有效性,这个函数会在参数不恰当时用
throwAsCaller
来抛出错误。 - defaultValue:形式参数的默认值,如果没有提供参数,那么就会使用这个默认值,这样就能实现类似于Python中的默认参数的功能。
这里的几个要素,都是可选的,可以根据实际情况来选择是否使用。
1function ret = abc(x1, x2, x3)
2 arguments
3 x1 (1,1) double = - 1.0
4 x2 (1,1) double = 0.0
5 x3 (1,1) double = 1.0
6 end
7 ret = x1 + x2 + x3;
8end
调用的方式可以是:
1[abc(), abc(1), abc(1,2), abc(1,2,3)]
ans =
0 2 4 6
当我们调用函数abc
时,如果输入了不符合的参数,那么就会抛出错误。
验证函数
Matlab提供了一些内置的验证函数,可以用于验证参数的有效性,常见的,有如下几种。
- 数值特性
- 大于0,
mustBePositive
- 大于等于0,
mustBeNonnegative
- 小于0,
mustBeNegative
- 小于等于0,
mustBeNonpositive
- 整数,
mustBeInteger
- 有限数,
mustBeFinite
- 大于0,
- 比较特性
- 大于某个值,
mustBeGreaterThan
- 小于某个值,
mustBeLessThan
- 大于某个值,
- 数据类型
- 数值,
mustBeNumeric
- 必须是某个类型,
mustBeA
- 数值,
- 大小
- 非空,
mustBeNonempty
- 行向量,
mustBeRow
- 列向量,
mustBeColumn
- 矩阵,
mustBeMatrix
- 非空,
- 范围和成员
- 大小在某个范围内,
mustBeInRange
- 是某个集合的成员,
mustBeMember
- 大小在某个范围内,
- 文本
- 文件,
mustBeFile
- 文件夹,
mustBeFolder
- 文件,
- 类型
- 类型,
mustBeType
- 类型或者空,
mustBeTypeOrEmpty
- 有效变量名称,
mustBeValidVariableName
- 类型,
如果内置的验证函数不能满足需求,我们也可以自定义验证函数,只需要满足如下的条件。
- 函数的输入参数是要验证的参数。
- 函数内部使用
throwAsCaller
来抛出错误。 - 或者调用
error
来抛出错误。
在使用自定义验证函数时,我们可以使用如下的语法形式。
1function ret = nonsense(x1, x2, x3)
2 arguments
3 x1 {myValidator1}
4 x2 {myValidator2(x2, 10)}
5 x3 {myValidator3(x3, x1)}
6 end
7 ret = numel(x1) + numel(x2) + numel(x3);
8end
9
10function myValidator1(x)
11 if ~isreal(x)
12 throwAsCaller(MException('myValidator1:NotReal', 'The input must be real.'));
13 end
14end
15
16function myValidator2(x, y)
17 if numel(x) < y
18 throwAsCaller(MException('myValidator2:SizeTooSmall', sprintf('The input size must be greater than %d.', y)));
19 end
20end
21
22function myValidator3(x, y)
23 if numel(x) < numel(y)
24 throwAsCaller(MException('myValidator3:X2SizeTooSmall', 'The input size x3 must not less than size x1.'));
25 end
26end
可以看到,这个函数有几个特点:当函数的参数就是形式参数时,可以忽略参数名称,直接写{myValidator1}
;当函数的参数除形式参数外还有别的参数时,需要写成完整的函数调用形式,
{myValidator2(x2, 10)}
,在调用中,可以使用已经定义的形式参数,也可以使用常量。
这个throwAsCaller
函数,可以用于抛出错误,这个错误会在调用函数的地方抛出,而不是在验证函数的地方抛出,这样就能更好的定位错误。
1nonsense(1,1:11,3)
ans =
13
命名参数的使用
在arguments
块中,用类似于结构体的方式来定义参数,这样就可以实现命名参数的功能。
1function printScore(x, options)
2 arguments
3 x (1,1) double = 0
4 options.Name (1,1) string = "Anonymous"
5 options.Age (1,1) double = 18
6 end
7
8fprintf('name: %s, age: %d, score: %f\n', options.Name, options.Age, x);
9end
这样,我们就可以使用如下的方式来调用函数。
1printScore()
2printScore(60)
3printScore(60, Name="John Doe")
4printScore(60, Age=12)
5printScore(60, Name="John Doe", Age=12)
name: Anonymous, age: 18, score: 0.000000
name: Anonymous, age: 18, score: 60.000000
name: John Doe, age: 18, score: 60.000000
name: Anonymous, age: 12, score: 60.000000
name: John Doe, age: 12, score: 60.000000
输出参数
对于输出参数,我们可以使用如下的语法形式。除默认值之外,与输入参数的定义方式是一样的。
1arguments(Output)
2 argName1 (dimensions) class {validators}
3 ...
4 argNameN ...
5end
举个例子:
1function [xfinal,yfinal] = rotatePatch(angle)
2 arguments (Output)
3 xfinal {mustBePositive}
4 yfinal {mustBePositive}
5 end
6 xfinal = cos(angle);
7 yfinal = sin(angle);
8end
1% 获得输出的个数
2n = nargout(@printScore);
3% 利用逗号分割列表赋值输出的方式调用函数
4[xy{1:n}] = rotatePatch(0.1 * pi);
5% 利用逗号分割列表来把输出转化为数组
6[xy{:}]
ans =
0.9511 0.3090
重复参数
重复输入参数
当我们需要类似于plot
函数的重复参数时,可以使用如下的语法形式。
1arguments (Repeating)
2 argName1 (dimensions) class {validators}
3 ...
4 argNameN
5 ...
6 argNameM (dimensions) class {validators}
7end
这是,我们就能采取如下的方式来调用函数。
1func(arg1_1, ..., arg1_M, arg2_1, ..., arg2_M, arg3_1, ..., arg3_M)
而在函数的定义中,形式参数就会时一个元胞数组,这个元胞数组就会包含所有的重复参数。
1argName1 = {arg1_1, ..., arg3_1}
2argName2 = {arg1_2, ..., arg3_2}
3...
4argNameM = {arg1_M, ..., arg3_M}
例如,我们可以定义一个函数,用于绘制多条曲线:
1function fRepeat(x,y,style)
2 arguments (Repeating)
3 x (1,:) double
4 y (1,:) double
5 style {mustBeMember(style,["--",":"])}
6 end
7
8 % Reshape the cell arrays of inputs and call plot function
9 z = reshape([x;y;style],1,[]);
10 if ~isempty(z)
11 plot(z{:});
12 end
13end
x1 = 1:10; y1 = 1:10; s1 = “:”; x2 = 1:7; y2 = 1:1.5:10; s2 = “–”; fRepeat(x1,y1,s1,x2,y2,s2)
重复输出参数
同样,也可以设置重复输出参数:
1function vectorSum = repeatSum(a,b)
2 arguments (Input,Repeating)
3 a (1,:)
4 b (1,:)
5 end
6 arguments (Output,Repeating)
7 vectorSum (1,:)
8 end
9
10 n = numel(a);
11 vectorSum{n} = a{n} + b{n};
12 for i = 1:n-1
13 vectorSum{i} = a{i} + b{i};
14 end
15end
1x1 = [1 2];
2y1 = [3 4];
3x2 = [1; 0];
4y2 = [0; 1];
5[sum1,sum2] = repeatSum(x1,y1,x2,y2)
sum1 =
4 6
sum2 =
1 1
总结
arguments
块中,可以定义输入参数、输出参数、重复输入参数、重复输出参数。- 可以使用内置的验证函数,也可以自定义验证函数。
- 可以使用结构体的方式来定义命名参数。
throwAsCaller
可以用于抛出错误,error
也可以用于抛出错误。
文章标签
|-->matlab |-->arguments |-->function
- 本站总访问量:次
- 本站总访客数:人
- 可通过邮件联系作者:Email大福
- 也可以访问技术博客:大福是小强
- 也可以在知乎搞抽象:知乎-大福
- Comments, requests, and/or opinions go to: Github Repository