4 votes

MATLAB : Utilisation de inputParser avec varargin

J'ai une fonction pour laquelle j'aimerais passer des arguments par l'intermédiaire de varargin et utiliser le inputParser pour s'assurer que les intrants sont sains d'esprit. Certains arguments sont nécessaires, d'autres non. Voici un exemple :

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

J'aimerais pouvoir passer des arguments comme suit ; peu importe quelle paire est passée à quel moment, tant que les arguments requis sont présents. Un exemple d'appel pourrait donc être le suivant :

myFunc('numStates', 4, 'numInps', 2, 'numOUts', 3, 'X0', [4;0]);

Apparemment, cette syntaxe est illégale ; parse() s'attend à ce que les premiers arguments soient les valeurs requises, mais ils ne doivent pas être nommés explicitement, c'est-à-dire comme dans :

function myFunc(numStates, numInps, numOuts, X0, varargin)
    ...
    p.parse(numStates, numInps, numOuts, X0, varargin{:});

end

Existe-t-il un moyen simple de faire ce que je veux, c'est-à-dire la première fonction ? Je suppose que la chose la plus simple à faire est de réorganiser les éléments de varargin et expulser les noms des arguments, mais ce n'est pas très élégant.

7voto

dumbmatter Points 2792

La solution la plus élégante à laquelle je peux penser est de sous-classer inputParser . Vous pouvez donc faire quelque chose comme ceci (enregistrer sous 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

Modifier ensuite

    p = inputParser;

à

    p = myInputParser;

et votre code fonctionnera alors comme vous le souhaitez.

Notez qu'il se peut que cela ne traite pas correctement tous les cas de figure, et je ne l'ai pas testé de manière approfondie, mais cela fonctionne avec votre exemple de cas d'utilisation.

5voto

yuk Points 13497

Dans InputParser, vous pouvez ajouter ParameterName - ParameterValue ne s'associe qu'avec addParamValue . Ces arguments sont censés être facultatifs.

En guise de solution de contournement, vous pouvez ajouter tous vos paramètres à l'aide de la commande addParamValue et utiliser [] comme valeur par défaut pour les arguments requis.

Vous pouvez alors effectuer l'une des opérations suivantes :

  • ajouter "non vide" aux attributs dans validateattributes pour les arguments requis ( Toutefois, dans ce cas, le message d'erreur n'indiquera pas qu'il s'agit d'arguments obligatoires, mais qu'ils doivent être non vides. )
  • ou ajouter un chèque séparé (avec if o assert ) que les arguments requis doivent être non vides avec votre propre message d'erreur.

Vous n'êtes pas limité à l'utilisation [] . La valeur par défaut peut être n'importe quelle valeur non appropriée pour un paramètre particulier et facile à vérifier.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X