除了解析功能文件,是否有一种方式来获得的输入和输出参数的名称在Matlab中的函数?
例如,假设下面的函数文件:
divide.m
function [value, remain] = divide(left, right)
value = floor(left / right);
remain = left / right - value;
end
从功能之外,我想要得到的输出参数,在这里一个数组: ['value', 'remain']
同样的输入参数: ['left', 'right']
有没有一种简单的方法在MATLAB做到这一点? Matlab的通常似乎支持反映相当不错。
编辑背景:
这样做的目的是在一个窗口中的用户输入以呈现函数参数。 我正在写一种信号处理程序,以及函数来执行这些信号的操作都存储在一个子文件夹。 我已经有一个列表,从中用户可以选择每个函数的名称,但有些功能需要额外的参数(如平滑函数可能采取窗口大小作为参数)。
此刻,我可以添加一个新功能,该程序会发现子文件夹,用户可以选择它来执行操作。 什么我缺少的是对用户指定的输入和输出参数,在这里,我已经打了关在这里,我无法找到的函数的名称。
Answer 1:
如果您的问题被限制到要解析的简单情况函数声明行,主要功能在一个文件中(例如,你将不会被处理本地功能 , 嵌套函数或匿名函数 ),那么你就可以提取输入和输出参数的名字,因为他们使用一些标准的字符串操作,并在文件中出现 的正则表达式 。 该函数声明行有一个标准的格式,但你必须考虑到,由于一些变化:
- 数量不等的空白或空行,
- 的存在单行或块注释 ,和
- 具有申报上多行打散 。
(事实证明,占据了块注释是最棘手的部分...)
我已经把一个函数get_arg_names
将处理上述所有。 如果你给它的功能文件的路径,它会返回一个包含您的输入和输出参数字符串两个单元阵列(或空电池阵列,如果是没有的)。 需要注意的是可变的输入或输出列表功能将只列出'varargin'
或'varargout'
,分别为变量名。 这里的功能:
function [inputNames, outputNames] = get_arg_names(filePath)
% Open the file:
fid = fopen(filePath);
% Skip leading comments and empty lines:
defLine = '';
while all(isspace(defLine))
defLine = strip_comments(fgets(fid));
end
% Collect all lines if the definition is on multiple lines:
index = strfind(defLine, '...');
while ~isempty(index)
defLine = [defLine(1:index-1) strip_comments(fgets(fid))];
index = strfind(defLine, '...');
end
% Close the file:
fclose(fid);
% Create the regular expression to match:
matchStr = '\s*function\s+';
if any(defLine == '=')
matchStr = strcat(matchStr, '\[?(?<outArgs>[\w, ]*)\]?\s*=\s*');
end
matchStr = strcat(matchStr, '\w+\s*\(?(?<inArgs>[\w, ]*)\)?');
% Parse the definition line (case insensitive):
argStruct = regexpi(defLine, matchStr, 'names');
% Format the input argument names:
if isfield(argStruct, 'inArgs') && ~isempty(argStruct.inArgs)
inputNames = strtrim(textscan(argStruct.inArgs, '%s', ...
'Delimiter', ','));
else
inputNames = {};
end
% Format the output argument names:
if isfield(argStruct, 'outArgs') && ~isempty(argStruct.outArgs)
outputNames = strtrim(textscan(argStruct.outArgs, '%s', ...
'Delimiter', ','));
else
outputNames = {};
end
% Nested functions:
function str = strip_comments(str)
if strcmp(strtrim(str), '%{')
strip_comment_block;
str = strip_comments(fgets(fid));
else
str = strtok([' ' str], '%');
end
end
function strip_comment_block
str = strtrim(fgets(fid));
while ~strcmp(str, '%}')
if strcmp(str, '%{')
strip_comment_block;
end
str = strtrim(fgets(fid));
end
end
end
Answer 2:
MATLAB提供了一种方法,以获取有关类的元数据(使用信息meta
包),然而,这仅适用于OOP类不正规的功能。
一个窍门是写在飞行类的定义,它包含您想处理函数的源代码,并让MATLAB处理的源代码(这可能会非常棘手的解析如你想象:函数定义行跨越多行,实际定义之前的评论,等...)
所以你的情况创建的临时文件将如下所示:
classdef SomeTempClassName
methods
function [value, remain] = divide(left, right)
%# ...
end
end
end
可再传给meta.class.fromName
解析元数据...
这里是一个快速和肮脏实现这个技巧的:
function [inputNames,outputNames] = getArgNames(functionFile)
%# get some random file name
fname = tempname;
[~,fname] = fileparts(fname);
%# read input function content as string
str = fileread(which(functionFile));
%# build a class containing that function source, and write it to file
fid = fopen([fname '.m'], 'w');
fprintf(fid, 'classdef %s; methods;\n %s\n end; end', fname, str);
fclose(fid);
%# terminating function definition with an end statement is not
%# always required, but now becomes required with classdef
missingEndErrMsg = 'An END might be missing, possibly matching CLASSDEF.';
c = checkcode([fname '.m']); %# run mlint code analyzer on file
if ismember(missingEndErrMsg,{c.message})
% append "end" keyword to class file
str = fileread([fname '.m']);
fid = fopen([fname '.m'], 'w');
fprintf(fid, '%s \n end', str);
fclose(fid);
end
%# refresh path to force MATLAB to detect new class
rehash
%# introspection (deal with cases of nested/sub-function)
m = meta.class.fromName(fname);
idx = find(ismember({m.MethodList.Name},functionFile));
inputNames = m.MethodList(idx).InputNames;
outputNames = m.MethodList(idx).OutputNames;
%# delete temp file when done
delete([fname '.m'])
end
而仅仅作为运行:
>> [in,out] = getArgNames('divide')
in =
'left'
'right'
out =
'value'
'remain'
Answer 3:
这将是非常困难(读:不可能)一般功能做(想的事情就像varargin等)。 此外,在一般情况下,依靠变量名作为文件的形式可能是......不是你想要的。 我要提出一个不同的方法。
既然你控制的程序,怎么样确定各模块不仅与M文件,而且还带有额外信息的表项。 您可以记录额外的参数,函数本身,谱写当选项是布尔值之和作为复选框等
现在,放在哪里呢? 我建议有主M-file函数返回的结构,排序模块加载步骤,具有指向子功能(或嵌套函数),做实际工作的函数句柄。 这会保留单文件的设置,我敢肯定你想保留,并为你的模块更可配置的设置。
function module = divide_load()
module.fn = @my_divide;
module.name = 'Divide';
module.description = 'Divide two signals';
module.param(1).name = 'left';
module.param(1).description = 'left signal';
module.param(1).required_shape = 'columnvector';
% Etc, etc.
function [value, remain] = my_divide(left, right)
value = floor(left / right);
remain = left / right - value;
end
end
Answer 4:
当你不能从有关的内容进行了编程的langauge获取信息(例如,“反思”),你有步骤的语言之外。
另一个海报建议“正则表达式”,当应用到真正的解析程序,因为正则表达式无法分析上下文无关汉语语言总是失败。
为了可靠地做到这一点,你需要一个真正的M语言解析器,这将让您使用解析树。 那么这是相当容易的。
我们的DMS软件再造工具包具有可用于它的M语言解析器,并能做到这一点。
Answer 5:
你有没有考虑使用地图容器?
你可以沿着这些路线写你的函数。 。 。
function [outMAP] = divide(inMAP)
outMAP = containers.Map();
outMAP('value') = floor(inMAP('left') / inMAP('right'));
outMAP('remain') = inMAP('left') / inMAP('right') - outMAP('value');
end
...并呼吁他们这样的...
inMAP = containers.Map({'left', 'right'}, {4, 5});
outMAP = divide(inMAP);
...然后简单地使用下面的语法检查塔的变量名...
>> keys(inMAP)
ans =
'left' 'right'
Answer 6:
inputname(argnum)
http://www.mathworks.com/help/techdoc/ref/inputname.html 。
文章来源: How do I retrieve the names of function parameters in matlab?