我有一个函数,我想通过 varargin 为其传递参数,并使用 inputParser 来确保输入是正常的。有些参数是必需的,有些则不是。下面是一个例子:

function myFunc(varargin)
    p = inputParser;
    p.addRequired(...
            'numStates', ...
                @(x) validateattributes(x, {'numeric'}, ...
                {'scalar', 'integer', 'positive'}));
        p.addRequired(...
            'numInps', ...
                @(x) validateattributes(x, {'numeric'}, ...
                {'scalar', 'integer', 'positive'}));
        p.addRequired(...
            'numOuts', ...
                @(x) validateattributes(x, {'numeric'}, ...
                {'scalar', 'integer', 'positive'}));
        p.addRequired(...
            'X0', ...
                @(x) validateattributes(x, {'numeric'}, ...
                {'vector'}));
        p.addOptional(...
            'freq', 10, ...
                @(x) validateattributes(x, {'numeric'}, ...
                {'scalar', 'integer', 'positive'}));
        p.addOptional(...
            'SimulinkVariables', struct(), ...
                @(x) isa(x, 'struct'));

    p.parse(varargin{:});

    %# do stuff with variables
end

我希望能够按如下方式传递参数;只要所需的一对在那里,什么时候传入哪一对都无关紧要。所以一个示例调用可能是:
myFunc('numStates', 4, 'numInps', 2, 'numOUts', 3, 'X0', [4;0]);

显然,这种语法是非法的; parse() 期望其中的第一个参数是必需的值,但不应显式命名它们,即,如下所示:
function myFunc(numStates, numInps, numOuts, X0, varargin)
    ...
    p.parse(numStates, numInps, numOuts, X0, varargin{:});

end

有没有一种简单的方法可以让它做我想要的,即第一个功能?我想最简单的方法是重新排序 varargin 的元素并删除参数名称,但这并不是非常优雅。

最佳答案

我能想到的最优雅的解决方案是将 inputParser 子类化。所以你可以做这样的事情(另存为 myInputParser.m):

classdef myInputParser < inputParser
    properties
        required = {};
    end

    methods
        function obj = myInputParser
            obj = obj@inputParser;
        end

        function addRequired(obj, argname, validator)
            obj.required = {obj.required{:}, argname};
            obj.addOptional(argname, [], validator);
        end

        function parse(obj, varargin)
            params_input = varargin(1:2:end);
            for i=1:length(obj.required)
                if isempty(strmatch(obj.required{i}, params_input))
                    error(sprintf('Required named parameter %s was not passed to function', obj.required{i}));
                end
            end
            parse@inputParser(obj, varargin{:});
        end

    end
end

然后改变
    p = inputParser;


    p = myInputParser;

然后您的代码将按照您的意愿工作。

请注意,这可能无法正确处理所有边缘情况,我还没有对其进行广泛测试,但它确实适用于您的示例用例。

关于MATLAB:将 inputParser 与 varargin 结合使用,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/9221690/

10-12 20:49