函数参量验证
函数参量验证是一种对函数参量声明特定限制的方法。使用参量验证,您可以约束参量的类、大小和其他方面,而无需在函数体中编写代码来执行这些测试。
函数参量验证是声明性的,这使得 MATLAB® 桌面工具能够通过检查特定代码块来提取关于函数的信息。通过声明参量的要求,您可以消除繁琐的参量检查代码,并提高代码的可读性、稳健性和可维护性。
函数参量验证语法简化了定义可选参量、重复参量和名称-值参量的过程。该语法还使您能够以一致的方式定义默认值。
何时使用参量验证
在函数定义中,您可以选择是否使用函数参量验证。如果函数可由任何代码调用,并且在执行函数代码之前必须确定参量的有效性,则参量验证能起到很大帮助。对于那些为他人使用而设计的函数,如能对参量施加适当限制,并允许基于参量验证检查返回特定错误消息,也可使用户受益。
何时不需要验证
在局部和私有函数中,以及在私有或受保护方法中,调用方知道输入要求,因此可以使用有效参量调用这些类型的函数。
何时不允许验证
在嵌套函数、抽象方法或句柄类析构函数方法中,不能使用参量验证语法。有关方法中参量验证的详细信息,请参阅方法语法。
arguments
代码块语法
函数在以关键字 arguments
和 end
起止的可选代码块中定义参量验证。如果使用,arguments
代码块必须在函数的第一个可执行代码行之前开始。
您可以在一个函数中使用多个 arguments
代码块,但是,所有这些代码块必须出现在不属于 arguments
代码块的代码之前。
下面代码中突出显示的部分展示了输入参量验证的语法。
函数参量声明可以包括以下任何一种限制:
大小 - 每个维度的长度,以圆括号括起
类 - 单个 MATLAB 类的名称
函数 - 以逗号分隔的验证函数列表,以花括号括起
您还可以在该参量的函数验证声明中为输入参量定义默认值。默认值必须满足对该参量声明的限制。
验证大小和类
大小
验证大小是参量的维数,用非负整数或冒号 (:
) 指定。冒号表示该维度中允许任何长度。您不能对维度使用表达式。在函数调用中分配给参量的值必须与指定的大小兼容,否则 MATLAB 会引发错误。
MATLAB 索引赋值规则适用于大小设定。例如,1×1 值与指定为 (5,3)
的大小兼容,因为 MATLAB 应用标量扩展。此外,MATLAB 行-列转换也适用,因此指定为 (1,:)
的大小可以接受 1×n 和 n×1 的大小。
下面给出了一些示例:
(1,1)
- 输入必须精确为 1×1。(3,:)
- 第一个维度必须为 3,第二个维度可以是任何值。
如果不指定大小,则允许任何大小,除非受到验证函数的限制。
类
验证类是单个类的名称。赋给函数输入的值必须属于指定的类或可转换为指定的类。使用 MATLAB 支持的任何 MATLAB 类或外部定义的类,但不包括 Java 类、COM 类和不使用 classdef
关键字的 MATLAB 类定义(在 MATLAB 软件版本 7.6 之前定义的类)。
下面给出了一些示例:
char
- 输入必须属于char
类,或是 MATLAB 可以转换为char
的值,例如string
。double
- 输入可以是任意精度的数值。cell
- 输入必须为元胞数组。用户定义的类
如果不指定类,则允许任何类,除非受到验证函数的限制。
示例:基本参量验证
此 arguments
代码块指定三个输入的大小和类。
function out = myFunction(A, B, C) arguments A (1,1) string B (1,:) double C (2,2) cell end % Function code ... end
在此函数中,变量必须满足以下验证要求:
A
是字符串标量。B
是 1×任意长度的双精度值向量。C
是 2×2 元胞数组。
验证函数
验证函数是一个 MATLAB 函数,如果参量值不满足某些要求,该函数会引发错误。验证函数不返回值,并且与类和大小不同,验证函数无法更改它们正在验证的参量的值。
在验证过程中,MATLAB 将参量值传递给为该参量列出的每个验证函数。传递给验证函数的值是在设定类和大小时进行任意转换之后的结果。MATLAB 从左到右调用每个函数,并引发遇到的第一个错误。
有关预定义的验证函数的表,请参阅参量验证函数。
示例:使用验证函数设置特定限制
验证函数可以用更具体的方式限制参量。您可以将预定义的验证函数用于许多常见类型的验证,并且可以定义自己的验证函数来满足特定要求。
例如,此函数使用 mustBeNumeric
、mustBeReal
、mustBeMember
及局部函数 mustBeEqualSize
指定以下验证。
输入
x
必须为任意长度的实数数值行向量。输入
v
必须为与x
大小相同的实数数值行向量。输入
method
必须为字符向量且是三个允许的选项之一。由于method
指定默认值,此参量是可选的。
function myInterp(x,v,method) arguments x (1,:) {mustBeNumeric,mustBeReal} v (1,:) {mustBeNumeric,mustBeReal,mustBeEqualSize(v,x)} method (1,:) char {mustBeMember(method,{'linear','cubic','spline'})} = 'linear' end % Function code .... end % Custom validation function function mustBeEqualSize(a,b) % Test for equal size if ~isequal(size(a),size(b)) eid = 'Size:notEqual'; msg = 'Size of first input must equal size of second input.'; error(eid,msg) end end
避免在自定义验证函数中使用函数参量验证。如需定义验证函数的详细信息,或要查看预定义验证函数列表,请参阅参量验证函数。
默认值
输入参量默认值可以是满足大小、类和验证函数要求的任何常量或表达式。在参量声明中指定默认值会使参量变为可选。当参量不包含在函数调用中时,MATLAB 将使用默认值。默认值表达式在每次使用默认值时进行计算。
注意
由于 MATLAB 仅在不带参量值调用函数时才验证默认值,因此无效的默认值仅在不带相应参量值调用函数时才会导致错误。
可选参量必须位于函数签名中和 arguments
代码块中的必需参量后。有关可选参量的详细信息,请参阅验证必需和可选位置参量。
转换为声明的类和大小
类验证和大小验证都可以更改参量的值。以下是 MATLAB 可以执行的一些转换示例。
为了满足类限制,支持以下功能:
char
值可以转换为string
值。single
值可以转换为double
。
为了满足大小限制,支持以下功能:
标量扩展可以将输入大小从标量变为非标量。
列向量可以转换为行向量。
因此,函数体中经过验证的值可能不同于调用函数时传递的值。有关类转换的详细信息,请参阅Implicit Class Conversion。为了避免验证过程中的类和大小转换,请改用参量验证函数。有关详细信息,请参阅使用验证函数以避免不必要的类和大小转换。
示例:值转换
以下函数说明如何转换输入以匹配在 arguments
代码块中指定的类。SpeedEnum
类是为定义第三个参量允许的值而创建的枚举类。
function forwardSpeed(a,b,c) arguments a double b char c SpeedEnum end % Function code disp(class(a)) disp(class(b)) disp(class(c)) end
以下代码定义该枚举类。
classdef SpeedEnum < int32 enumeration Full (100) Half (50) Stop (0) end end
该函数调用使用的输入值可由 MATLAB 转换为声明的类型。函数中实际的参量类型则显示为输出。
forwardSpeed(int8(4),"A string",'full')
double char SpeedEnum
输出参量验证
从 R2022b 开始,可以对输出参量使用参量验证。与输入参量类似,您可以验证输出参量的类和大小,还可以应用验证函数。但是,您无法为输出参量指定默认值,也无法引用以前声明的参量。输出参量验证始终是可选的。添加输出参量验证有助于提高代码的可读性,并在可能随时间而变化的代码中使输出保持一致。
必须使用单独的 arguments
块来验证输入和输出参量。在 arguments
语句后定义参量块 (Input)
或 (Output)
的类型。如果同时使用 (Input)
和 (Output)
参量块,则 (Output)
块必须跟在 (Input)
块后。如果没有指定类型,则 MATLAB 假定该块包含输入参量。
有关详细信息,请参阅 arguments
。
示例:验证输出参量
从 R2022b 开始,可以对输出参量使用参量验证。
例如,此函数使用单独的参量块验证三个输入参量和输出参量的大小和类。请注意,(Input)
块必须在 (Output)
块之前。
function out = myFunction(A, B, C) arguments (Input) A (1,1) string B (1,:) double C (2,2) cell end arguments (Output) out (1,:) double end % Function code ... end
参量的种类
函数参量验证可以声明四种参量。函数可以定义四种参量中的任何一种,但参量必须按照以下顺序定义:
参量类型 | 其他信息 |
---|---|
1.必需位置参量 | 验证必需和可选位置参量 |
2.可选位置参量 | |
3.重复位置参量 | 验证重复参量 |
4.可选名称-值参量 | 验证名称-值参量 |
参量验证的顺序
在调用函数时,MATLAB 按照参量在 arguments
块中的声明顺序从上往下验证输入参量。上一个参量完全验证后,才会继续验证下一个参量。这就确保引用较早声明的参量时,使用的是经过验证的值。在第一次验证失败时,函数会引发错误。
经过验证的值可能不同于调用函数时作为输入传递的原始值。例如,此函数将输入声明为类 uint32
值。第三个输入声明指定了一个默认值,该值等于前两个输入的乘积。
function c = f(a, b,c) arguments a uint32 b uint32 c uint32 = a.* b end % Function code ... end
如果使用其他数值类(例如 double
)的输入来调用函数,则输入会被转换为 uint32
。
c = f(1.8,1.5)
由于在函数调用中没有指定可选参量 c
,因此在将 a
和 b
转换为 uint32
值后,MATLAB 会计算默认值并将其赋给 c
。在本例中,两个输入的转换结果均为值 2。因此,a
和 b
的乘积是 4。
c = uint32 4
如果您为第三个输入指定值,则该函数会为 c
赋值,并且不会计算默认值表达式。
c = f(1.8,1.5,25)
c = uint32 25
变量和函数访问的限制
arguments
代码块存在于函数的工作区中。使用 import
命令添加到函数作用域的任何包、类或函数都将添加到 arguments
代码块的作用域中。
对验证器函数和默认值表达式可见的变量只有已声明的输入变量。在以下函数中,c
的默认值派生自 a
和 b
。
function c = f(a,b,c) arguments a uint32 b uint32 c uint32 = a * b end % Function code ... end
但是,您无法引用尚未在 arguments
代码块中声明的输入变量。例如,在上述函数中对参量 a
使用以下声明是无效的,因为 b
和 c
尚未声明。
arguments a uint32 = b * c b uint32 c uint32 end
参量验证表达式只能引用此前声明过(因此经过验证)的参量。名称-值参量的验证函数和默认值无法访问其他名称-值参量。
arguments
代码块中函数的限制
对此前所声明参量的任何引用必须在验证函数和默认值的文本中可见。为了确保代码透明,请不要使用与函数工作区交互的函数。尤其不要在 arguments
代码块中使用嵌套函数或下表中列出的任何函数。
assignin | builtin | clear |
dbstack | eval | evalc |
evalin | exist | feval |
input | inputname | load |
nargin | narginchk | nargoutchk |
save | whos | who |
这些限制仅适用于 arguments
代码块,对函数体中的变量或函数则不适用。
调试参量块
在参量块内部调试时,工作区为只读。这意味着可以检查工作区并查看赋给变量的值。但是,当工作区为只读时,无法创建新变量或更改赋给现有变量的值。一旦调试器位于参量块之外,就可以再次创建或编辑变量。