MATLAB 函数参数检查
为了得到健壮的代码,我们非常有必要对函数的参数进行检查,除了最基础的参数个数,还需要关注参数的类型和数据范围等,下面介绍几个MATLAB提供的用于参数检查的内置函数。
validateattributes
validateattributes
函数可以为我们检查某个具体参数的类型以及是否满足某些要求,不满足要求会抛出错误。
假设我们有一个函数func1
,它接受两个输入参数a
和b
,我们要求:a
是一个非空的标量,b
是一个非空的向量。
1
2
3
4
5
6
7function result = func1(a, b)
validateattributes(a, {'numeric'}, {'nonempty', 'scalar'});
validateattributes(b, {'numeric'}, {'nonempty', 'vector'});
result = a + sum(b);
disp(['Result: ', num2str(result)]);
end
validateattributes
函数可以确保a
是一个非空的标量,b
是一个非空的向量。如果输入参数不符合这些要求,MATLAB
会抛出错误。
validateattributes
函数的基本格式为 1
validateattributes(a, classes, attributes);
其中:
- 第一个参数是要检查的函数参数
- 第二个参数是要求的类型,通常包括:
double
,logical
,char
,struct
- 第三个参数是要求参数满足的条件,可以是多个条件,例如
{'nonempty', 'vector'}
,也可以留空{}
关于参数的类型,MATLAB提供了class
函数来获取,常见的类型包括:
double
浮点数numeric
数值类型(包括各种浮点数和各种整数)char
字符logical
布尔值struct
结构体数组cell
元胞数组function_handle
函数句柄class_name
自定义类型名称
关于参数满足的条件,常见的条件包括
- 维度检查
2d
二维数组;3d
三维数组row
行向量;column
列向量;vector
行向量或列向量scalar
标量'size',[d1,...dN]
指定维数信息的数组'numel',N
指定元素总个数为N
的数组'nrows',N
指定行数为N
的数组;'ncols',N
指定列数为N
的数组square
方阵(每一个维度都相等)nonempty
要求数组的每一个维度都不为0nonsparse
要求数组非稀疏
- 大小范围检查
'>',N
所有值大于N
'>=',N
所有值大于等于N
- ...
- 其它检查
finite
数组中的元素不含有Inf
nonnan
数组中的元素不含有Nan
nonnegative
数组中的元素全部非负nonzero
数组中的元素全部非零decreasing
单调减increasing
单调增
validatestring
对于字符串参数,MATLAB专门提供了检查工具validatestring
,它可以限制字符串参数的所有合法取值,例如
1
2
3
4
5
6
7
8
9
10
11
12function result = selectOption(option)
option = validatestring(option, {'Option1', 'Option2', 'Option3'});
switch option
case 'Option1'
result = 'You selected Option 1';
case 'Option2'
result = 'You selected Option 2';
case 'Option3'
result = 'You selected Option 3';
end
end
但是这种限制不是严格的,正如很多MATLAB内置函数一样,可以忽略大小写进行模糊匹配,也可以只匹配到合法选项的开头部分。 如果这个参数只能匹配到唯一的合法选项,就不会报错,反之则会报错。
成功的模糊匹配例如 1
2
3
4
5
6>> validatestring('G',{'green','red'})
ans =
'green'
>> validatestring('bla',{'black','blue'})
ans =
'black'
下面的匹配则会报错 1
2
3
4
5
6
7
8>> validatestring('u',{'black','blue'})
Expected input to match one of these values:
'black', 'blue'
The input, 'u', did not match any of the valid values.
>> validatestring('ue',{'black','blue'})
Expected input to match one of these values:
'black', 'blue'
The input, 'ue', did not match any of the valid values.
inputParser
inputParser
是输入参数解析器类型,和C++中常见的命令行参数解析器非常类似,只不过在这里是对函数参数进行检查。
假设我们有一个函数func2
,它接受两个必需的输入参数a
和b
,一个可选的输入参数c
,以及一个键值对参数Verbose
。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27function result = func2(a, b, varargin)
% 创建一个 inputParser 对象
p = inputParser;
% 配置必需参数
p.addRequired('a', @isnumeric);
p.addRequired('b', @isnumeric);
% 配置可选参数(默认值1)
p.addOptional('c', 1, @isnumeric);
% 配置键值对参数(键值对的值默认取false)
p.addParameter('Verbose', false, @islogical);
% 解析输入参数
p.parse(a, b, varargin{:});
% 重新获取解析后的参数
a = p.Results.a;
b = p.Results.b;
c = p.Results.c;
verbose = p.Results.Verbose;
result = a + sum(b) + c;
if verbose
disp(['a: ', num2str(a)]);
disp(['b: ', num2str(b)]);
disp(['c: ', num2str(c)]);
disp(['Result: ', num2str(result)]);
end
end
在这个示例中,我们首先创建了一个inputParser
对象
p,然后用它对参数进行检查:
- 使用
addRequired
方法添加了必需参数a
和b
,并指定它们必须是数值类型。 - 使用
addOptional
方法添加了可选参数c
,并指定默认值为 1。 - 使用
addParameter
方法添加了键值对参数Verbose
,指定键的名称为Verbose
,值必须是布尔类型,默认为false
。 - 使用
parse
方法解析输入参数。 - 从
p.Results
重新获取解析后的参数。
使用例如 1
2
3
4
5
6
7
8
9
10
11% 调用 func2 并传递必需参数 a 和 b
func2(1, [2, 3]);
% 调用 func2 并传递必需参数 a 和 b 以及可选参数 c
func2(1, [2, 3], 4);
% 调用 func2 并传递必需参数 a 和 b,以及名称-值对参数 'Verbose'
func2(1, [2, 3], 'Verbose', true);
% 调用 func2 并传递必需参数 a 和 b, 可选参数 c 和名称-值对参数 'Verbose'
func2(1, [2, 3], 4, 'Verbose', true);
我们可以使用匿名函数的方式,将validateattributes
函数也组合到inputParser
中使用,用于判断参数的有效性,例如
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29function result = myFunction(a, b, varargin)
% 创建一个 inputParser 对象
p = inputParser;
% 设置输入参数保持顺序
p.KeepUnmatched = true;
% 必需参数
addRequired(p, 'a', @(x) validateattributes(x, {'numeric'}, {'scalar', 'nonnegative'}));
addRequired(p, 'b', @(x) validateattributes(x, {'numeric'}, {'vector'}));
% 可选参数
addOptional(p, 'c', 1, @(x) validateattributes(x, {'numeric'}, {'scalar', 'nonnegative'}));
% 名称-值对参数
addParameter(p, 'Verbose', false, @(x) validateattributes(x, {'logical'}, {'scalar'}));
% 解析输入参数
parse(p, a, b, varargin{:});
% 重新获取解析后的参数
a = p.Results.a;
b = p.Results.b;
c = p.Results.c;
verbose = p.Results.Verbose;
result = a + sum(b) + c;
if verbose
disp(['a: ', num2str(a)]);
disp(['b: ', num2str(b)]);
disp(['c: ', num2str(c)]);
disp(['Result: ', num2str(result)]);
end
end