Hvordan kan jeg angi standardverdier for funksjoner parametere i Matlab?

stemmer
110

Er det mulig å ha standard argumenter i Matlab? For eksempel her:

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

Jeg ønsker å ha den ekte løsning, være en valgfri argument til bølgefunksjonen. Hvis det er mulig, kan hvem som helst vise den riktige måten å gjøre dette? For tiden er jeg prøver det jeg postet over og jeg får:

??? 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.
Publisert på 28/04/2009 klokken 00:46
kilden bruker
På andre språk...                            


16 svar

stemmer
140

Det er ikke en direkte måte å gjøre dette som du har forsøkt.

Den vanlige metoden er å bruke "varargs" og sjekke mot antall argumenter. Noe som:

function f(arg1, arg2, arg3)

  if nargin < 3
    arg3 =   'some default'
  end

end

Det er noen mer avansert ting du kan gjøre med isempty, etc., og du vil kanskje se på Matlab sentral for noen pakker som bunter disse slags ting.

Du kan ta en titt på varargin, nargchkosv De er nyttige funksjoner for denne typen ting. varargs tillate deg å la et variabelt antall endelige argumenter, men dette betyr ikke komme deg rundt problemet med standardverdier for noen / alle av dem.

Svarte 28/04/2009 kl. 00:55
kilden bruker

stemmer
1

Dette er mer eller mindre løftet fra Matlab manuell ; Jeg har bare fått bestått erfaring ...

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
Svarte 28/04/2009 kl. 00:59
kilden bruker

stemmer
10

Ja, det kan være veldig fint å ha muligheten til å gjøre som du har skrevet. Men det er ikke mulig i MATLAB. Mange av mine verktøy som lar standarder for argumentene har en tendens til å bli skrevet med eksplisitte sjekker i begynnelsen slik:

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

Ok, så jeg vil vanligvis bruke en bedre, mer beskrivende feilmelding. Se at sjekken til en tom variable gjør det mulig for brukeren å passere i en tom par braketter, [], som en plassholder for en variabel som vil ta på dens standardverdi. Forfatteren må fortsatt levere koden for å erstatte den tomme argumentet med standardverdien skjønt.

Mine verktøy som er mer sofistikert, med mange parametere, som alle har standard argumenter, vil ofte bruke en eiendom / verdi-par grensesnitt for standardargumenter. Denne grunnleggende paradigmet er sett i håndtaket grafikkverktøy i Matlab, samt i optimset, odeset, etc.

Som et middel til å jobbe med disse eiendom / verdi-par, må du lære om varargin, som en måte å inputing et fullt variabelt antall argumenter til en funksjon. I skrev (og postet) et verktøy for å arbeide med slike egenskapen / verdipar, parse_pv_pairs.m . Den hjelper deg å konvertere eiendom / verdi-par i en Matlab struktur. Den lar deg også til å levere standardverdier for hver parameter. Konvertering en uhåndterlig liste over parametere i en struktur er en veldig fin måte å passere dem rundt i MATLAB.

Svarte 28/04/2009 kl. 11:56
kilden bruker

stemmer
3

Jeg har funnet ut at parseArgs funksjonen kan være svært nyttig.

Svarte 28/04/2009 kl. 21:00
kilden bruker

stemmer
55

Jeg har brukt inputParsergjenstand å forholde seg til innstillingen standardvalgene. Matlab vil ikke godta python-lignende format du har angitt i spørsmålet, men du bør være i stand til å kalle funksjonen slik:

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

Når du har definert wavefunksjon som dette:

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{:});

Nå verdiene som sendes inn i funksjonen er tilgjengelig gjennom i_p.Results. Dessuten var jeg ikke sikker på hvordan å validere at para gått inn for ftruevar faktisk en inlinefunksjon så forlot validatoren tomt.

Svarte 02/05/2009 kl. 12:37
kilden bruker

stemmer
1

Matlab gir ikke en mekanisme for dette, men du kan bygge en i Userland kode som er terser enn inputParser eller "hvis nargin <1 ..." sekvenser.

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

Deretter kan du kaller det i din fungerer som dette:

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'});

Formateringen er en konvensjon som lar deg lese ned fra parameternavnene til standardverdiene. Kan utvide getargs () med valgfri parameter typen spesifikasjoner (for feildeteksjon eller implisitt omdannelse) og argument tellekjeder.

Det er to ulemper til denne tilnærmingen. Først er det sakte, slik at du ikke ønsker å bruke den for funksjoner som er kalt i sløyfer. For det andre, Matlab funksjon hjelp - autofullføring hint på kommandolinjen - ikke fungerer for varargin funksjoner. Men det er ganske praktisk.

Svarte 13/05/2009 kl. 04:18
kilden bruker

stemmer
0

kan det være lurt å bruke parseparamskommandoen i Matlab; bruken vil se ut:

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;
Svarte 08/10/2010 kl. 19:04
kilden bruker

stemmer
0
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;

f.eks f(2,4,'c',3)bevirker at parameteren cfor å være tre.

Svarte 11/10/2010 kl. 13:56
kilden bruker

stemmer
3

Det er også en 'hakke' som kan brukes selv om det kan bli fjernet fra Matlab på et eller annet punkt: Funksjons EVAL faktisk mulig å bruke to argumenter av hvilke den andre er drevet hvis det oppstår en feil med den første.

Dermed kan vi bruke

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

å bruke en verdi som standard for argumentet

Svarte 07/12/2010 kl. 09:30
kilden bruker

stemmer
18

En annen litt mindre Hacky måten er

function output = fun(input)
   if ~exist('input','var'), input='BlahBlahBlah'; end
   ...
end
Svarte 20/02/2011 kl. 15:21
kilden bruker

stemmer
2

Etter å ha blitt klar over ASSIGNIN (takk til dette svaret ved b3 ) og EVALIN skrev jeg to funksjoner for å endelig få en veldig enkel kall struktur:

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

Her er en oversikt:

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

og

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 ')']) ;
Svarte 22/03/2011 kl. 09:55
kilden bruker

stemmer
3

Jeg tror jeg har funnet ganske kjekk liten måte å håndtere dette problemet, tar opp bare tre linjer med kode (sperring linje wraps). Følgende er hentet direkte fra en funksjon jeg skriver, og det synes å fungere som ønsket:

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

Tenkte jeg skulle dele den.

Svarte 16/01/2014 kl. 14:18
kilden bruker

stemmer
3

Jeg er forvirret ingen har påpekt dette blogginnlegget ved Loren, en av Matlab utviklere. Tilnærmingen er basert på varargin, og unngår alle de endeløse og painfull if-then-elseeller switchtilfeller med convoluted forhold. Når det er noen standardverdier, er effekten dramatisk . Her er et eksempel fra den koblede bloggen:

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{:};

Hvis du fortsatt ikke får det, så prøv å lese hele bloggen av Loren. Jeg har skrevet en oppfølging blogginnlegg som omhandler manglende posisjonstandardverdier. Jeg mener at du kan skrive noe sånt som:

somefun2Alt(a, b, '', 42)

og fortsatt ha epsstandardverdien for tolparameteren (og @magictilbakeringings for funcselvfølgelig). Loren kode gjør dette med en liten, men vanskelig modifisering.

Til slutt, bare noen få fordeler med denne metoden:

  1. Selv med mye mislighold standardteksten koden ikke få stor (i motsetning til familien av if-then-elsetilnærminger, som blir lengre for hver nye standardverdi)
  2. Alle standardene er på ett sted. Hvis noen av de som trenger å endre, har du bare ett sted å se på.

Trooth bli fortalt, er det en ulempe også. Når du skriver funksjonen i Matlab skall og glemme sine parametere, vil du se en unhelpful vararginsom et hint. For å håndtere dette, blir du bedt om å skrive en meningsfull bruk klausul.

Svarte 06/04/2014 kl. 19:01
kilden bruker

stemmer
0

Hvis du vil bruke oktav du kunne gjøre det på denne måten - men dessverre Matlab ikke støtter denne muligheten

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

(tatt fra doc )

Svarte 10/06/2014 kl. 14:09
kilden bruker

stemmer
5

Dette er min enkle måte å sette standardverdier til en funksjon ved hjelp av "prøve":

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

Hilsen!

Svarte 09/06/2015 kl. 14:01
kilden bruker

stemmer
0

Jeg liker å gjøre dette i en noe mer objektorientert måte. Før du ringer wave () lagre noen av dine argumenter i en struct, f.eks. et kalt parametere:

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

Innenfor bølgefunksjonen deretter kontrollere, om struct parametrene inneholder et felt kalt 'flagg', og hvis så, hvis verdi er ikke tom. Deretter tilordne den eighter en standardverdi du definere før, eller verdien gitt som et argument i parametrene 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

Dette gjør det lettere å håndtere et stort antall argumenter, fordi det ikke er avhengig av rekkefølgen av de gitte argumenter. Når det er sagt, er det også nyttig hvis du må legge til flere argumenter senere, fordi du ikke trenger å endre funksjoner signatur å gjøre det.

Svarte 24/05/2018 kl. 12:04
kilden bruker

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more