IT story

Matlab에서 함수 매개 변수의 기본값을 어떻게 설정합니까?

hot-time 2020. 7. 17. 07:59
반응형

Matlab에서 함수 매개 변수의 기본값을 어떻게 설정합니까?


Matlab에 기본 인수를 사용할 수 있습니까? 예를 들면 다음과 같습니다.

function wave(a, b, n, k, T, f, flag, fTrue=inline('0'))

진정한 해결책이 wave 함수에 대한 선택적 인수가 되길 원합니다. 가능하다면 누구나 올바른 방법을 보여줄 수 있습니까? 현재, 나는 위에 게시 한 것을 시도하고 있습니다.

??? Error: File: wave.m Line: 1 Column: 37
The expression to the left of the equals sign is not a valid target for an assignment.

시도한 것처럼 직접 수행 할 수있는 방법은 없습니다.

일반적인 방법은 "varargs"를 사용하고 인수 수를 확인하는 것입니다. 다음과 같은 것 :

function f(arg1, arg2, arg3)

  if nargin < 3
    arg3 =   'some default'
  end

end

isempty등으로 할 수있는 더 멋진 일이 있으며 이러한 종류의 묶음을 묶은 일부 패키지에 대해 Matlab central을 살펴볼 수 있습니다.

당신은 한 번 봐있을 수 있습니다 varargin, nargchk이런 종류의 물건에 대한, 등 그들은있는 거 유용한 기능입니다. varargs를 사용하면 가변 수의 최종 인수를 남길 수 있지만 일부 / 모든 기본값의 문제를 해결할 수는 없습니다.


inputParser기본 옵션 설정을 처리하기 위해 객체를 사용했습니다 . Matlab은 질문에 지정한 파이썬과 같은 형식을 허용하지 않지만 다음과 같이 함수를 호출 할 수 있어야합니다.

wave(a,b,n,k,T,f,flag,'fTrue',inline('0'))

다음 wave과 같이 함수 를 정의한 후 :

function wave(a,b,n,k,T,f,flag,varargin)

i_p = inputParser;
i_p.FunctionName = 'WAVE';

i_p.addRequired('a',@isnumeric);
i_p.addRequired('b',@isnumeric);
i_p.addRequired('n',@isnumeric);
i_p.addRequired('k',@isnumeric);
i_p.addRequired('T',@isnumeric);
i_p.addRequired('f',@isnumeric);
i_p.addRequired('flag',@isnumeric); 
i_p.addOptional('ftrue',inline('0'),1);    

i_p.parse(a,b,n,k,T,f,flag,varargin{:});

이제 함수에 전달 된 값을 통해 사용할 수 있습니다 i_p.Results. 또한 전달 된 매개 변수 ftrue가 실제로 inline함수 인지 확인하는 방법을 확신하지 못했기 때문에 유효성 검사기를 비워 두었습니다.


약간 덜 해킹 된 또 다른 방법은

function output = fun(input)
   if ~exist('input','var'), input='BlahBlahBlah'; end
   ...
end

그렇습니다. 당신이 작성한대로 할 수있는 능력을 갖는 것이 정말 좋을 것입니다. 그러나 MATLAB에서는 불가능합니다. 인수의 기본값을 허용하는 많은 유틸리티는 처음에 다음과 같이 명시적인 검사로 작성되는 경향이 있습니다.

if (nargin<3) or isempty(myParameterName)
  MyParameterName = defaultValue;
elseif (.... tests for non-validity of the value actually provided ...)
  error('The sky is falling!')
end

좋아, 일반적으로 더 나은 설명 오류 메시지를 적용합니다. 빈 변수를 검사하면 기본값으로 사용될 변수의 자리 표시 자로 빈 대괄호 []를 전달할 수 있습니다. 저자는 빈 인수를 기본값으로 바꾸려면 여전히 코드를 제공해야합니다.

모든 기본 인수가있는 MANY 매개 변수를 사용하여보다 정교한 유틸리티는 종종 기본 인수에 특성 / 값 쌍 인터페이스를 사용합니다. 이 기본 패러다임은 matlab의 핸들 그래픽 도구와 최적화, odeset 등에서 볼 수 있습니다.

이러한 속성 / 값 쌍으로 작업하기위한 수단으로, 함수에 완전 가변 개수의 인수를 입력하는 방법으로 varargin에 대해 배워야합니다. 나는 그러한 속성 / 값 쌍 parse_pv_pairs.m 과 함께 작동하는 유틸리티를 작성하고 게시 했습니다 . 속성 / 값 쌍을 MATLAB 구조로 변환하는 데 도움이됩니다. 또한 각 매개 변수에 기본값을 제공 할 수 있습니다. 다루기 어려운 매개 변수 목록을 구조로 변환하는 것은 MATLAB에서 매개 변수를 전달하는 아주 좋은 방법입니다.


이것은 "try"를 사용하여 기본값을 함수로 설정하는 간단한 방법입니다.

function z = myfun (a,varargin)

%% Default values
b = 1;
c = 1;
d = 1;
e = 1;

try 
    b = varargin{1};
    c = varargin{2};
    d = varargin{3};
    e = varargin{4};
end

%% Calculation
z = a * b * c * d * e ;
end

문안 인사!


parseArgs 함수가 매우 유용 하다는 것을 알았습니다 .


어떤 시점에서 matlab에서 제거 될 수 있지만 사용할 수있는 'hack'도 있습니다. eval 함수는 실제로 첫 번째 오류가 발생하면 두 번째 인수가 실행되는 두 개의 인수를 허용합니다.

따라서 우리는 사용할 수 있습니다

function output = fun(input)
   eval('input;', 'input = 1;');
   ...
end

인수의 기본값으로 값 1을 사용하려면


나는이 문제를 해결할 수있는 아주 좋은 방법을 찾았으며 세 줄의 코드 (줄 바꿈 제외) 만 취했다고 생각합니다. 다음은 내가 작성하는 기능에서 직접 해제되었으며 원하는대로 작동하는 것 같습니다.

defaults = {50/6,3,true,false,[375,20,50,0]}; %set all defaults
defaults(1:nargin-numberForcedParameters) = varargin; %overload with function input
[sigma,shifts,applyDifference,loop,weights] = ...
     defaults{:}; %unfold the cell struct

내가 공유 할 줄 ​​알았는데


Matlab의 개발자 중 한 명인 Loren 이이 블로그 게시물지적한 사람이 아무도 없습니다 . 접근 방식은 기반으로 varargin하고 모든 끝없는 고통 스럽다 방지 if-then-else또는 switch뒤얽힌 조건의 경우입니다. 기본값 이 몇 개 있으면 효과가 극적으로 나타납니다 . 다음은 링크 된 블로그의 예입니다.

function y = somefun2Alt(a,b,varargin)
% Some function that requires 2 inputs and has some optional inputs.

% only want 3 optional inputs at most
numvarargs = length(varargin);
if numvarargs > 3
    error('myfuns:somefun2Alt:TooManyInputs', ...
        'requires at most 3 optional inputs');
end

% set defaults for optional inputs
optargs = {eps 17 @magic};

% now put these defaults into the valuesToUse cell array, 
% and overwrite the ones specified in varargin.
optargs(1:numvarargs) = varargin;
% or ...
% [optargs{1:numvarargs}] = varargin{:};

% Place optional args in memorable variable names
[tol, mynum, func] = optargs{:};

그래도 얻을 수 없다면 Loren의 전체 블로그 게시물을 읽으십시오. 위치 기본값 누락 된 후속 블로그 게시물작성했습니다 . 나는 당신이 다음과 같은 것을 쓸 수 있음을 의미합니다.

somefun2Alt(a, b, '', 42)

and still have the default eps value for the tol parameter (and @magic callback for func of course). Loren's code allows this with a slight but tricky modification.

Finally, just a few advantages of this approach:

  1. Even with a lot of defaults the boilerplate code doesn't get huge (as opposed to the family of if-then-else approaches, which get longer with each new default value)
  2. All the defaults are in one place. If any of those need to change, you have just one place to look at.

Trooth be told, there is a disadvantage too. When you type the function in Matlab shell and forget its parameters, you will see an unhelpful varargin as a hint. To deal with that, you're advised to write a meaningful usage clause.


After becoming aware of ASSIGNIN (thanks to this answer by b3) and EVALIN I wrote two functions to finally obtain a very simple calling structure:

setParameterDefault('fTrue', inline('0'));

Here's the listing:

function setParameterDefault(pname, defval)
% setParameterDefault(pname, defval)
% Author: Tobias Kienzler (https://stackoverflow.com/users/321973)
% sets the parameter NAMED pname to the value defval if it is undefined or
% empty

if ~isParameterDefined('pname')
    error('paramDef:noPname', 'No parameter name defined!');
elseif ~isvarname(pname)
    error('paramDef:pnameNotChar', 'pname is not a valid varname!');
elseif ~isParameterDefined('defval')
    error('paramDef:noDefval', ['No default value for ' pname ' defined!']);
end;

% isParameterNotDefined copy&pasted since evalin can't handle caller's
% caller...
if ~evalin('caller',  ['exist(''' pname ''', ''var'') && ~isempty(' pname ')'])
    callername = evalin('caller', 'mfilename');
    warnMsg = ['Setting ' pname ' to default value'];
    if isscalar(defval) || ischar(defval) || isvector(defval)
        warnMsg = [warnMsg ' (' num2str(defval) ')'];
    end;
    warnMsg = [warnMsg '!'];
    warning([callername ':paramDef:assigning'], warnMsg);
    assignin('caller', pname, defval);
end

and

function b = isParameterDefined(pname)
% b = isParameterDefined(pname)
% Author: Tobias Kienzler (https://stackoverflow.com/users/321973)
% returns true if a parameter NAMED pname exists in the caller's workspace
% and if it is not empty

b = evalin('caller',  ['exist(''' pname ''', ''var'') && ~isempty(' pname ')']) ;

This is more or less lifted from the Matlab manual; I've only got passing experience...

function my_output = wave ( a, b, n, k, T, f, flag, varargin )
  optargin = numel(varargin);
  fTrue = inline('0');
  if optargin > 0
    fTrue = varargin{1};
  end
  % code ...
end

Matlab doesn't provide a mechanism for this, but you can construct one in userland code that's terser than inputParser or "if nargin < 1..." sequences.

function varargout = getargs(args, defaults)
%GETARGS Parse function arguments, with defaults
%
% args is varargin from the caller. By convention, a [] means "use default".
% defaults (optional) is a cell vector of corresponding default values

if nargin < 2;  defaults = {}; end

varargout = cell(1, nargout);
for i = 1:nargout
    if numel(args) >= i && ~isequal(args{i}, [])
        varargout{i} = args{i};
    elseif numel(defaults) >= i
        varargout{i} = defaults{i};
    end
end

Then you can call it in your functions like this:

function y = foo(varargin)
%FOO 
%
% y = foo(a, b, c, d, e, f, g)

[a, b,  c,       d, e, f, g] = getargs(varargin,...
{1, 14, 'dfltc'});

The formatting is a convention that lets you read down from parameter names to their default values. You can extend your getargs() with optional parameter type specifications (for error detection or implicit conversion) and argument count ranges.

There are two drawbacks to this approach. First, it's slow, so you don't want to use it for functions that are called in loops. Second, Matlab's function help - the autocompletion hints on the command line - don't work for varargin functions. But it is pretty convenient.


you might want to use the parseparams command in matlab; the usage would look like:

function output = wave(varargin);
% comments, etc
[reg, props] = parseparams(varargin);
ctrls = cell2struct(props(2:2:end),props(1:2:end),2);  %yes this is ugly!
a = reg{1};
b = reg{2};
%etc
fTrue = ctrl.fTrue;

function f(arg1, arg2, varargin)

arg3 = default3;
arg4 = default4;
% etc.

for ii = 1:length(varargin)/2
  if ~exist(varargin{2*ii-1})
    error(['unknown parameter: ' varargin{2*ii-1}]);
  end;
  eval([varargin{2*ii-1} '=' varargin{2*ii}]);
end;

e.g. f(2,4,'c',3) causes the parameter c to be 3.


if you would use octave you could do it like this - but sadly matlab does not support this possibility

function hello (who = "World")
  printf ("Hello, %s!\n", who);
endfunction

(taken from the doc)


I like to do this in a somewhat more object oriented way. Before calling wave() save some of your arguments within a struct, eg. one called parameters:

parameters.flag =42;
parameters.fTrue =1;
wave(a,b,n,k,T,f,parameters);

Within the wave function then check, whether the struct parameters contains a field called 'flag' and if so, if its value is non empty. Then assign it eighter a default value you define before, or the value given as an argument in the parameters struct:

function output = wave(a,b,n,k,T,f,parameters)
  flagDefault=18;
  fTrueDefault=0;
  if (isfield(parameters,'flag') == 0 || isempty(parameters.flag)),flag=flagDefault;else flag=parameters.flag; end
  if (isfield(parameter,'fTrue') == 0 || isempty(parameters.fTrue)),fTrue=fTrueDefault;else fTrue=parameters.fTrue; end
  ...
end

This makes it easier to handle large numbers of arguments, because it does not depend on the order of the given arguments. That said, it is also helpful if you have to add more arguments later, because you don't have to change the functions signature to do so.

참고URL : https://stackoverflow.com/questions/795823/how-do-i-set-default-values-for-functions-parameters-in-matlab

반응형