如何在 Matlab 中编码:如果参数为空,则默认为“x”值?

计算科学 matlab
2021-11-29 12:57:41

我有一个带有许多参数的函数,但其​​中一些是可选的。

1.) 如果在调用函数时,有些是空的,我该如何对其进行编码以使其默认为特定值?

2.) 如果 5 个参数中有 3 个是可选的,代码如何识别将哪一个设置为默认值?例如:

function [u, v] = somefxn(required, required2, optional, optional2, optional3)

并说当我调用这个函数时,只有optional2填充。

更新:有什么我可以使用的说

if optional2 is empty
    return default_value
end
4个回答

当参数的顺序发生变化时,您可以使用不易中断的方式执行此操作inputParser(),这也允许您验证参数。

一个例子在这里(看看setup_params()从第 178 行开始的函数)。更多带有示例的文档在这里

这是一个例子:

1) 在 Matlab 中,如果使用varargin,则必须提供所有前面的可选参数(即optional必须与 一起给出optional2)。在这种情况下(例如,如果您调用somefxm(myarg, myarg2, myoptarg, myoptarg2),那么您可以根据varargin(2) 的长度知道只optional3需要应用默认值。您可以使用 if 语句来说明类似

if length(varargin) == 2
    optional3 = 3;  % or whatever
end

您可以使用其他条件语句来处理只有一个可选参数(例如length(varargin) == 1)或没有可选参数(例如length(varargin) == 0)的情况。

2)请注意,使用此方案,Matlab 无法知道哪个函数参数适合哪个选项,因此您必须保持所有内容按顺序排列。如果您需要更大的灵活性,您可以通过在参数前面加上描述性字符串来执行类似关键字参数的操作,这是一些常见函数的plot工作方式。然后你要么需要编写逻辑来解析varargin(如 Christian Clason 的评论),要么你可以使用该inputParser对象。

编辑

另一种(在我看来,更笨重)处理“空”optional2的方法是测试提供的参数是否只是一个空矩阵,

if isempty(cell2mat(varargin(2))
    optional2 = 3; % or whatever
end

然后,您可以somefxn使用“空”的第二个可选参数调用:

somefxn(myarg, myarg2, myoptarg, [], myoptarg3)

然后,第二个可选参数将分配给您在函数中编码的任何内容。如果你这样做,你需要确保一个空矩阵不是一个有效的参数somefxn,否则你只是重载了正确的行为。

Matlab 中的输入参数处理真的很烦人。这有效:

function out = foobar(foo, bar, baz)
    if ~exist('baz', 'var') ||  isempty(baz)
        baz = 'default_value';
    end

这需要对所有可选输入参数重复。优点:它也不依赖于函数定义中参数的顺序。另一种选择是所有nargin黑客:

if nargin < 3 || isempty(baz)
    baz = 'baz';
    if nargin < 2 || isempty(bar)
        bar = 'bar';
        if nargin < 1 || isempty(foo)
             foo = 'foo';
        end
    end
 end

显然这是丑陋的并且不是很可扩展;加上它取决于参数的定义顺序。

最后一个选项可能是 inputParser,但我不知道如何使用它轻松完成“isempty”部分。我在@DavidKetcheson 发布的示例中找不到这种类型的输入处理。

编辑:@FedericoPoloni 提到了另一种选择:选项结构。我认为如果您有很多输入参数(并且如果您在解析未知字段名称以规避 FredericoPoloni 提到的混淆时抛出错误),它们是可以的。我会使用这样的东西:

function test(foobar, opts)

default_opts.foo = 'foo';
default_opts.bar = 'bar';

if nargin > 1
    opts = parse_opts(default_opts, opts);
end

并作为一个单独的功能:

function parsed_opts = parse_opts(default_opts, in_opts)

in_fields = fieldnames(in_opts);
n_in_fields = numel(in_fields);

parsed_opts = default_opts;

for i_field = 1:numel(in_fields)
    cur_field = in_fields{i_field};

    if isfield(default_opts, cur_field)
        parsed_opts.(cur_field) = in_opts.(cur_field);
    else
        error('parse_opts:input', 'Unknown field name `%s`', cur_field);
    end
end

让我在列表中添加另一种在 Matlab 中经常使用但我推荐的方法来反对它:options结构。

基本上,您的语法需要一个额外的选项 struct opts,并且您检查特定字段的存在。例子:

>> options.TolX=1-e-3;
>> x=fzero(fun,x0,options)

% in fzero.m
function x=fzero(fun,x0,options)
if not(isfield(options,'TolX'))
    tol=defaultTolerance;
else
    tol=options.TolX;
end

这是在几个标准的 Matlab 方法中使用的,例如我在这个例子中使用的fzero 。

你不应该这样做的主要原因是错误检查很糟糕:如果你有一个字段options.tolX(缺少大写 T),事情通常会默默地出错。