【问题标题】:inputParser without varargin没有可变参数的输入解析器
【发布时间】:2017-03-08 09:03:55
【问题描述】:

我想在函数f(a,b,c,d) 上使用 inputParser,其中 a 是必需的,b-d 是可选的。我想保留 b-d 命名 = 不使用 f(a, varargin),因为当您真正想要使用该函数时,该 varargin 不会告诉您任何内容。除非给出所有 4 个参数,否则简单的 p.parse(a,b,c,d) 显然不起作用。

我知道如何做到这一点的唯一方法是使用setDefaultValue(argname, value),然后在需要时使用p.parse(...) 进行检查。但是有没有一种简单的方法来破解这个只使用 inputParser(没有大量的 ifs)?

作为一个附带问题,没有简单的方法可以像在 MATLAB 中的 C# 中那样执行命名参数,对吧?所以我会拥有f(a,b,c,d) 并照此使用。第一个参数是 a,然后是 b,然后是 c ...但是当用户想像 f(a, 'd', 3, 'c', 2) 一样调用它时,他可以。在此示例中,他将保留默认值 b,并为 d 使用 3,为 c 使用 2。当然,没有大量工作在我这边 - 我知道该怎么做,编写自己的解析,但我想要一个更简单的解决方案(就像其他人的解析:))

【问题讨论】:

  • “因为当你真正想使用这个函数时,varargin 并没有告诉你任何事情”。那就写文档吧!不要因为你懒写10行cmets就破坏MATLAB
  • @AnderBiguri 我确实写过文档,但我个人觉得在写函数名时查看函数所需的参数非常有帮助。因此,我尝试向我的代码的用户提供相同的功能。说我的矩形(中心,高度,宽度)。看到参数名称通常就足以知道您应该输入哪一个,甚至不需要打开帮助或文档。然后在文档中列出所有选项、默认值等,以及函数的确切作用、示例等。
  • MATLAB 显示了这一点。它将显示f(a,b,...),然后是“更多帮助”的链接
  • @AnderBiguri 当函数定义为f(a,varargin) 时,它将显示为f(a,...),这没有多大帮助 - 您需要打开帮助才能查看bc 的顺序和d(或在myRectangle 示例中为heightwidth)。因此,在主要使用名称/值对或很少使用可选参数时,我倾向于使用 varargin。
  • 我认为 MATLAB 决定这样做是因为它们的某些函数可以采用大量可选参数。能够在屏幕上显示它们会用那个据说很小的黄色框挡住一半的屏幕。因此,它显示了您需要使用的内容,所有可选的,请转到文档。

标签: matlab


【解决方案1】:

我要给你一个替代答案:不要偷懒,写文档。

如果你这样做:

function [out]= foo(a,b,c,d)
%FOO does foo things
%
% FOO(a,b) does very foo thins to a and b
%
% FOO(a,b,c) is quite foo-y on c also
%
% FOO(a,b,c,d) c and d are optional FOO things

if (nargin==3)
...

那么如果用户按下F1 或输入help foo 他们将获得cmets 中的所有信息。


为了让用户能够在我的代码中输入foo(1,2,'d',5) 等输入,我使用以下"inputparser" 作为可选参数:

function [c,d]=parse_inputs(argin)
opts=     {'c','d'};
defaults=ones(length(opts),1);
% Check inputs
nVarargs = length(argin);
if mod(nVarargs,2)
    error('InvalidInput','Invalid number of inputs')
end

% check if option has been passed as input
for ii=1:2:nVarargs
    ind=find(ismember(opts,lower(argin{ii})));
    if ~isempty(ind)
        defaults(ind)=0;
    else
       error('InvalidInput',['Optional parameter "' argin{ii} '" does not exist' ]); 
    end
end

for ii=1:length(opts)
    opt=opts{ii};
    default=defaults(ii);
    % if one option is not default, then extrac value from input
    if default==0
        ind=double.empty(0,1);jj=1;
        while isempty(ind)
            ind=find(isequal(opt,lower(argin{jj})));
            jj=jj+1;
        end
         if isempty(ind)
            error('InvalidInput',['Optional parameter "' argin{jj} '" does not exist' ]); 
        end
        val=argin{jj};
    end

    switch opt
        case 'c': 
          if default;
             c=4;
          else
             c=val;
          end
     ...
     otherwise
            error('InvalidInput',['Invalid input name:', num2str(opt),'\n No such option in SART()']);
    end
end

那么我在 foo 里面做的第一件事就是:

[c,d]=parse_inputs(varargin);

【讨论】:

    【解决方案2】:

    Ander Biguri's answer 很好地回答了关于如何在没有 varargin 的情况下处理不同数量的输入的问题的第一部分。

    关于如何成对解析输入的问题的第二部分,这是我的简化“输入解析器”

    function parseVarargin( argin )
    % Simplified function to parse varargin property-value pairs
    
    % Read input arguments
    if mod(numel(argin),2)
        error('Uneven number of inputs')
    end
    for i = 1 : 2 : numel(argin)-1
        if ~ischar(argin{i})
            error('Properties must be strings')
        end
        isValid = evalin('caller', sprintf('exist(''%s'',''var'')', argin{i}));
        if isValid && ~strcmp(argin{i},'MRX')
            assignin('caller', argin{i}, argin{i+1})
        else
            error(['Undefined property %s. ', ...
                'Please note case-sensitivity.'], argin{i});
        end
    end
    

    要使用它,只需设置默认变量值并在varargin 上调用parseVarargin

    function foo( a, varargin )
    %FOO general description
    %
    % Usage:
    %   foo(a)
    %   foo(a, 'property-value-pairs')
    % 
    % Properties:
    %   b : This ...
    %   c : That ...
    
    % Default property values
    b = 1;
    c = [];
    
    % Read property-value paris
    parseVarargin( varargin );
    
    % Do other stuff
    

    【讨论】:

      猜你喜欢
      • 2017-07-02
      • 1970-01-01
      • 1970-01-01
      • 2020-09-26
      • 2020-06-05
      • 2013-05-21
      • 2018-11-13
      • 1970-01-01
      • 2018-10-27
      相关资源
      最近更新 更多