Matlab中的默认参数

是否有可能在Matlab中有默认参数? 例如,在这里:

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

我希望真正的解决scheme是波函数的可选参数。 如果可能的话,任何人都可以certificate正确的做法吗? 目前,我正在尝试上面发布的内容,并得到:

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

谢谢!

据我所知,没有直接的方法可以像你一样尝试。

通常的做法是使用可变参数并检查参数的数量。 就像是:

 function f(arg1,arg2,arg3) if nargin < 3 arg3 = 'some default' end end 

有些东西你可以用isempty等来做,而且你可能想看看matlab中心的一些软件包捆绑这些东西。

[更新]很高兴帮助。

你可能会看看varargin,nargchk等等,它们对于这类事情是有用的function。 可变参数允许你留下可变数量的最终参数,但这并不能解决某些/所有参数的默认值问题。

我已经使用inputParser对象来处理设置默认选项。 Matlab不会接受你在问题中指定的python-like格式,但你应该能够像这样调用函数:

 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传入函数的值。 另外,我不确定如何validation传入的参数实际上是一个inline函数,所以将validation器留空。

另一个稍微不太好的方法是

 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 

好的,所以我通常会应用一个更好,更具描述性的错误信息。 看到一个空variables的检查允许用户传递一个空括号[]作为占位符,作为一个variables的占位符,该variables将采用默认值。 尽pipe如此,作者仍然需要提供代码来将该空参数replace为默认值。

我的实用程序更复杂,使用MANY参数,所有这些参数都有默认参数,通常使用属性/值对接口作为默认参数。 这个基本范例可以在matlab中的句柄graphics工具中看到,也可以在optimize,odeset等中看到。

作为使用这些属性/值对的手段,您需要了解varargin,作为向函数input完全可变数量参数的一种方式。 我写了(并发布)一个实用程序来处理这样的属性/值对, parse_pv_pairs.m 。 它可以帮助您将属性/值对转换为matlab结构。 它还使您能够为每个参数提供默认值。 将一个笨拙的参数列表转换成一个结构是一个非常好的方式在MATLAB中传递它们。

我发现parseArgs函数可以是非常有用的。

还有一个'黑客',可以使用,虽然它可能会从某些时候从matlab中删除:函数eval实际上接受两个参数,其中第二个运行,如果第一个错误发生。

因此我们可以使用

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

使用值1作为参数的默认值

这是我使用“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 

问候!

在意识到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 ')']) ; 

我相信我find了一个很好的方法来处理这个问题,只占用三行代码(禁止换行)。 以下是直接从我正在写的一个函数中解脱出来的,而且它似乎按照需要工作:

 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-elseswitch具有复杂条件的情况。 当有一些默认值时,效果是显着的 。 以下是链接的博客示例:

 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的整篇博客文章。 我已经写了一篇关于缺less位置默认值的后续博文 。 我的意思是说你可以写下如下的东西:

 somefun2Alt(a, b, '', 42) 

并仍然有tol参数的默认eps值(和@magiccallbackfunc当然)。 罗兰的代码允许这个轻微,但棘手的修改。

最后,这种方法的几个优点:

  1. 即使有很多默认值,样板代码也不会变得很大(与if-then-else方法相比,每个新的默认值都会变得更长)
  2. 所有的默认值都在一个地方。 如果有任何需要改变的地方,你只能看一个地方。

特鲁特被告知,也有一个劣势。 当你在Matlab shell中键入函数并忘记它的参数时,你会看到一个无用的varargin作为提示。 为了解决这个问题,build议您写一个有意义的使用条款。

这或多或less地从Matlab手册中解除; 我只有传球的经验

 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没有为此提供一种机制,但是你可以构build一个比inputParser或“if nargin <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'}); 

格式化是一种惯例,可以让您从参数名称读取到其默认值。 您可以使用可选的参数types规范(用于错误检测或隐式转换)和参数计数范围来扩展getargs()。

这种方法有两个缺点。 首先,它很慢,所以你不想用它在循环中调用的函数。 其次,Matlab的函数帮助 – 命令行上的自动补全提示 – 不适用于varargin函数。 但是很方便。

你可能想在matlab中使用parseparams命令; 用法如下所示:

 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; 

例如f(2,4,'c',3)导致参数c为3。

如果你使用八度,你可以这样做 – 但遗憾的是matlab不支持这种可能性

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

(取自doc )