मैं मतलाब में फ़ंक्शन मापदंडों के लिए डिफ़ॉल्ट मान कैसे सेट करूं?


127

क्या मतलाब में डिफ़ॉल्ट तर्क होना संभव है? उदाहरण के लिए, यहां:

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

मैं चाहूंगा कि सही समाधान तरंग फ़ंक्शन का एक वैकल्पिक तर्क हो। यदि यह संभव है, तो क्या कोई ऐसा करने का उचित तरीका प्रदर्शित कर सकता है? वर्तमान में, मैं कोशिश कर रहा हूँ कि मैंने ऊपर क्या पोस्ट किया है और मुझे यह मिला:

??? 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.

जवाबों:


151

ऐसा करने का कोई सीधा तरीका नहीं है जैसा आपने प्रयास किया है।

सामान्य दृष्टिकोण "वार्गर्स" का उपयोग करना और तर्कों की संख्या के खिलाफ जांच करना है। कुछ इस तरह:

function f(arg1, arg2, arg3)

  if nargin < 3
    arg3 =   'some default'
  end

end

कुछ कट्टरपंथी चीजें हैं जो आप के साथ कर सकते हैं isempty, आदि, और आप कुछ पैकेजों के लिए मतलाब केंद्रीय को देखना चाह सकते हैं जो इन प्रकार की चीजों को बंडल करते हैं।

आप पर एक नज़र हो सकता है varargin, nargchkआदि वे उपयोगी चीज की इस तरह के लिए कार्य करता है। varargs आपको अंतिम तर्कों की एक चर संख्या छोड़ने की अनुमति देता है, लेकिन यह आपको उनमें से कुछ / सभी के लिए डिफ़ॉल्ट मानों की समस्या के आसपास नहीं मिलता है।


58

मैंने प्रयोग किया है inputParser डिफ़ॉल्ट विकल्पों को सेट करने के वस्तु का । मतलाब ने आपके द्वारा प्रश्न में निर्दिष्ट अजगर-जैसा प्रारूप स्वीकार नहीं किया है, लेकिन आपको इस तरह से फ़ंक्शन को कॉल करने में सक्षम होना चाहिए:

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फ़ंक्शन था इसलिए सत्यापनकर्ता को खाली छोड़ दिया गया था।


7
जैसा कि सबसे अच्छा मैं बता सकता हूं, यह पसंदीदा तरीका है। यह साफ-सुथरा, स्व-दस्तावेजीकरण (अधिक स्टेटमन्स का एक गुच्छा if nargin), बनाए रखने के लिए आसान, कॉम्पैक्ट और लचीला है।
JnBrymn

19

एक और थोड़ा कम हैकी तरीका है

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

यह विकल्प काम नहीं करता है यदि आप सी कोड उत्पन्न करने के लिए MATLAB कोडर का उपयोग करने जा रहे हैं, क्योंकि कोडर "मौजूद" फ़ंक्शन का समर्थन नहीं करता है।
डेव टिलमैन

10

हाँ, यह वास्तव में अच्छा हो सकता है जैसा आपने लिखा है। लेकिन 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 में हैंडल ग्राफिक्स टूल्स के साथ-साथ ऑप्टिमसेट, ओडसेट आदि में भी देखा जाता है।

इन प्रॉपर्टी / वैल्यू पेयर के साथ काम करने के साधन के रूप में, आपको किसी फ़ंक्शन के लिए पूरी तरह से परिवर्तनशील तर्कों को इनपुट करने के तरीके के रूप में, वैरगिन के बारे में जानने की आवश्यकता होगी। मैंने ऐसी संपत्ति / मूल्य जोड़े, parse_pv_pairs.m के साथ काम करने के लिए एक उपयोगिता (और पोस्ट) लिखी । यह आपको संपत्ति / मूल्य जोड़े को एक मैटलैब संरचना में बदलने में मदद करता है। यह आपको प्रत्येक पैरामीटर के लिए डिफ़ॉल्ट मानों की आपूर्ति करने में भी सक्षम बनाता है। एक संरचना में मापदंडों की एक अनिर्दिष्ट सूची में परिवर्तित करना MATLAB में उन्हें पास करने का एक बहुत अच्छा तरीका है।


7

"कोशिश" का उपयोग करके फ़ंक्शन के लिए डिफ़ॉल्ट मान सेट करने का यह मेरा सरल तरीका है:

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

सादर!



3

एक 'हैक' भी है जिसका उपयोग किया जा सकता है, हालांकि इसे कुछ बिंदु पर मटलब से हटाया जा सकता है: फ़ंक्शन eval वास्तव में दो तर्कों को स्वीकार करता है जिनमें से दूसरा चलाया जाता है यदि पहली के साथ कोई त्रुटि हुई।

इस प्रकार हम उपयोग कर सकते हैं

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

तर्क के लिए डिफ़ॉल्ट के रूप में मान 1 का उपयोग करें


3

मेरा मानना ​​है कि मुझे इस मुद्दे से निपटने के लिए केवल तीन पंक्तियों (कोडिंग लाइन रैप्स) को लेकर काफी निफ़्टी तरीका मिला। निम्नलिखित एक समारोह मैं सीधे लिख रहा हूँ से उठा लिया है, और यह वांछित के रूप में काम करने लगता है:

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

बस सोचा था कि मैं इसे साझा करूंगा।


3

मैं उलझन में हूँ कि किसी ने लोटेन के इस ब्लॉग पोस्ट को मतलाब के डेवलपर्स में से एक बताया है। दृष्टिकोण पर आधारित है 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{:};

यदि आप अभी भी इसे प्राप्त नहीं करते हैं, तो लोरेन द्वारा पूरे ब्लॉग पोस्ट को पढ़ने का प्रयास करें। मैंने एक अनुवर्ती ब्लॉग पोस्ट लिखी है, जो लापता डिफ़ॉल्ट मूल्यों से संबंधित है। मेरा मतलब है कि आप कुछ ऐसा लिख ​​सकते हैं:

somefun2Alt(a, b, '', 42)

और अभी भी पैरामीटर के epsलिए डिफ़ॉल्ट मान है tol(और @magicकॉलबैक के लिएfunc पाठ्यक्रम के )। लोरेन का कोड इसे मामूली लेकिन मुश्किल संशोधन के साथ अनुमति देता है।

अंत में, इस दृष्टिकोण के कुछ फायदे:

  1. बहुत सारे डिफॉल्ट्स के साथ भी बॉयलरप्लेट कोड बहुत बड़ा नहीं होता है (जैसा कि परिवार के विरोध में होता है if-then-else दृष्टिकोण , जो प्रत्येक नए डिफ़ॉल्ट मान के साथ लंबा हो जाता है)
  2. सभी चूक एक ही स्थान पर हैं। यदि उनमें से किसी को बदलने की आवश्यकता है, तो आपके पास देखने के लिए सिर्फ एक जगह है।

ट्रूथ को बताया जाए, नुकसान भी है। जब आप माटलब शेल में फ़ंक्शन टाइप करते हैं और इसके मापदंडों को भूल जाते हैं, तो आप vararginएक संकेत के रूप में एक अनहेल्दी देखेंगे । उससे निपटने के लिए, आपको एक सार्थक उपयोग क्लॉज लिखने की सलाह दी जाती है।


आपके अनुवर्ती ब्लॉग पोस्ट का लिंक टूट गया है; क्या आप इसे ठीक कर सकते हैं?
equaeghe

2

ASSIGNIN ( b3 द्वारा इस उत्तर के लिए धन्यवाद ) और EVALIN के बारे में जानने के बाद मैंने अंततः एक बहुत ही सरल कॉलिंग संरचना प्राप्त करने के लिए दो कार्य लिखे:

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

यहाँ सूचीबद्ध है:

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

तथा

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

1

यह मटलब मैनुअल से अधिक या कम उठाया गया है ; मैंने केवल अनुभव प्राप्त किया है ...

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

1
कोड में कुछ त्रुटियां थीं जिन्हें मैंने ठीक किया। सबसे पहले, "ऑप्टारगिन" को परिभाषित करने की आवश्यकता है। दूसरा, "वैरगिन" एक सेल ऐरे है जो बाद के सभी इनपुट को इकट्ठा करता है, इसलिए आपको मूल्यों को हटाने के लिए सेल ऐरे इंडेक्सिंग का उपयोग करना होगा।
gnovice

मुझे अपनी दृष्टि की जाँच करवाने की आवश्यकता है; मैं कसम खाता हूं कि मैंने कल मैनुअल में कोई भी नहीं देखा :(
काइल

@ केश: चिंता करने की नहीं, हम सभी गलतियाँ करते हैं। इसलिए मुझे SO की विकि-ईश शैली पसंद है: अगर मैं कुछ मूर्खतापूर्ण टाइपो बनाता हूं, तो आमतौर पर कोई और व्यक्ति होता है जो इसे पकड़ सकता है और इसे जल्दी से मेरे लिए ठीक कर सकता है। =)
gnovice

1

मतलाब इसके लिए एक तंत्र प्रदान नहीं करता है, लेकिन आप उपयोगकर्तालैंड कोड में एक का निर्माण कर सकते हैं जो कि इनपुटपर्सर या "यदि नर्गिन <1 ..." अनुक्रम से अधिक कठिन है।

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

तब आप इसे इस तरह से अपने कार्यों में बुला सकते हैं:

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

फ़ॉर्मेटिंग एक कन्वेंशन है जो आपको पैरामीटर नामों से नीचे उनके डिफ़ॉल्ट मानों को पढ़ने देता है। आप वैकल्पिक पैरामीटर प्रकार विनिर्देशों (त्रुटि का पता लगाने या अंतर्निहित रूपांतरण के लिए) और तर्क गणना श्रेणियों के साथ अपने गेटअर्ज () का विस्तार कर सकते हैं।

इस दृष्टिकोण में दो कमियां हैं। सबसे पहले, यह धीमा है, इसलिए आप इसे उन कार्यों के लिए उपयोग नहीं करना चाहते हैं जिन्हें लूप में कहा जाता है। दूसरा, मैटलैब का कार्य मदद करता है - कमांड लाइन पर स्वत: पूर्णता संकेत - वैरगिन कार्यों के लिए काम नहीं करता है। लेकिन यह बहुत सुविधाजनक है।


0

आप parseparamsmatlab में कमांड का उपयोग करना चाह सकते हैं ; उपयोग की तरह दिखेगा:

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;

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(2,4,'c',3)लिए पैरामीटर c3 होता है।


0

यदि आप ऑक्टेव का उपयोग करते हैं तो आप इसे इस तरह से कर सकते हैं - लेकिन दुख की बात है कि मैटलैब इस संभावना का समर्थन नहीं करता है

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

( डॉक्टर से लिया गया )


0

मैं इसे कुछ और अधिक उन्मुख तरीके से करना पसंद करता हूं। कॉल करने से पहले तरंग () एक संरचना के भीतर अपने कुछ तर्क बचाएं, जैसे। एक पैरामीटर कहा जाता है:

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

लहर फ़ंक्शन के भीतर, फिर जांचें कि क्या संरचनात्मक मापदंडों में 'ध्वज' नामक फ़ील्ड शामिल है और यदि ऐसा है, तो यदि इसका मान गैर रिक्त है। इसके बाद इसे निर्धारित करें कि आप पहले परिभाषित डिफ़ॉल्ट मान, या पैरामीटर संरचना में एक तर्क के रूप में दिया गया मान:

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

इससे बड़ी संख्या में तर्कों को संभालना आसान हो जाता है, क्योंकि यह दिए गए तर्कों के क्रम पर निर्भर नहीं करता है। यदि आपने बाद में और अधिक तर्क जोड़े हैं, तो यह भी उपयोगी है, क्योंकि ऐसा करने के लिए आपको कार्य हस्ताक्षर बदलने की आवश्यकता नहीं है।


नाम-मूल्य जोड़े के MATLAB मानक का पालन क्यों नहीं किया जाता है? wave(a,b,'flag',42,'fTrue',1)
संकट लुएंगो

यह निश्चित रूप से एक विकल्प के रूप में अच्छी तरह से है, खासकर जब एक ही कुछ पैरामीटर है। हालांकि, बड़ी संख्या में नाम-मूल्य वाले जोड़े के साथ कॉलिंग वेव () कोड की पठनीयता को कम कर सकती है। इसलिए मैं अक्सर कुछ इनपुट को स्ट्रक्चर्स में ग्रुप करना पसंद करता हूं।
CheshireCat
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.