是否可以在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.
答案 0 :(得分:145)
没有像你尝试过的那样直接做到这一点。
通常的方法是使用“varargs”并检查参数的数量。类似的东西:
function f(arg1, arg2, arg3)
if nargin < 3
arg3 = 'some default'
end
end
您可以使用isempty
等进行一些更好的事情,并且您可能希望查看Matlab中心以获取捆绑这些内容的一些软件包。
你可能会看一下varargin
,nargchk
等等。它们对于这类事情是有用的功能。 varargs允许您保留可变数量的最终参数,但这并不能解决部分/全部默认值的问题。
答案 1 :(得分:57)
我使用inputParser
对象来处理设置默认选项。 Matlab不会接受你在问题中指定的类似python的格式,但你应该可以像这样调用函数:
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
函数,因此将验证器留空。
答案 2 :(得分:18)
另一种稍微不那么粗暴的方式是
function output = fun(input)
if ~exist('input','var'), input='BlahBlahBlah'; end
...
end
答案 3 :(得分: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
好的,所以我通常会应用更好,更具描述性的错误消息。请注意,检查空变量允许用户传入一对空括号[],作为将采用其默认值的变量的占位符。作者仍然必须提供代码,用其默认值替换该空参数。
我的实用程序更复杂,有许多参数,所有参数都有默认参数,它们通常会使用属性/值对接口作为默认参数。这个基本范例可以在matlab的handle图形工具中看到,也可以在optimset,odeset等中看到。
作为使用这些属性/值对的一种方法,您需要了解varargin,作为向函数输入完全可变数量的参数的方法。我编写(并发布)了一个实用程序来处理这些属性/值对parse_pv_pairs.m。它可以帮助您将属性/值对转换为matlab结构。它还允许您为每个参数提供默认值。将笨拙的参数列表转换为结构是一种非常好的方法,可以在MATLAB中传递它们。
答案 4 :(得分:5)
这是我将默认值设置为函数的简单方法,使用&#34;尝试&#34;:
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
问候!
答案 5 :(得分:3)
我发现parseArgs功能非常有用。
答案 6 :(得分:3)
虽然可能会在某些时候从matlab中删除,但也可以使用'hack': 函数eval实际上接受两个参数,如果第一个参数发生错误,则运行第二个参数。
因此我们可以使用
function output = fun(input)
eval('input;', 'input = 1;');
...
end
使用值1作为参数的默认值
答案 7 :(得分: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
以为我会分享它。
答案 8 :(得分:3)
我感到很困惑,没有人通过Matlab的开发人员之一Loren指出this blog post。该方法基于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的整篇博文。我写了一篇跟进blog post来处理缺少位置默认值。我的意思是你可以这样写:
somefun2Alt(a, b, '', 42)
并且仍然具有eps
参数的默认tol
值(当然,@magic
还有func
回调)。 Loren的代码允许进行轻微但棘手的修改。
最后,这种方法的一些优点是:
if-then-else
方法系列相反,每个新默认值都会变得更长)varargin
作为提示。为了解决这个问题,建议你写一个有意义的使用条款。
答案 9 :(得分:2)
了解ASSIGNIN后(感谢this answer 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 ')']) ;
答案 10 :(得分:1)
这或多或少取自Matlab manual;我只有过往经历...
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
答案 11 :(得分:1)
Matlab没有为此提供机制,但您可以在userland代码中构造一个比inputParser或“if nargin&lt; 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'});
格式化是一种允许您从参数名称读取其默认值的约定。您可以使用可选的参数类型规范(用于错误检测或隐式转换)和参数计数范围来扩展getargs()。
这种方法有两个缺点。首先,它很慢,所以你不想将它用于循环中调用的函数。其次,Matlab的函数帮助 - 命令行上的自动完成提示 - 不适用于varargin函数。但这很方便。
答案 12 :(得分:0)
你可能想在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;
答案 13 :(得分: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;
e.g。 f(2,4,'c',3)
导致参数c
为3。
答案 14 :(得分:0)
如果你使用八度,你可以这样做 - 但遗憾的是matlab不支持这种可能性
function hello (who = "World")
printf ("Hello, %s!\n", who);
endfunction
(摘自doc)
答案 15 :(得分:0)
我喜欢以更加面向对象的方式做到这一点。 在调用wave()之前,在结构中保存一些参数,例如。一个叫做参数:
parameters.flag =42;
parameters.fTrue =1;
wave(a,b,n,k,T,f,parameters);
在wave函数中,然后检查struct参数是否包含一个名为'flag'的字段,如果是,则其值是否为非空。然后为它指定一个你之前定义的默认值,或者在参数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
这使得处理大量参数变得更容易,因为它不依赖于给定参数的顺序。也就是说,如果您以后必须添加更多参数也很有帮助,因为您不必更改函数签名。