打印当前代码行和特定变量的名称、类型和维度
Printing current code line and specific variables' names, types and dimensions
要调试我的 Octave/MATLAB 代码,我希望能够执行如下操作:
A = magic(3);
b = 42;
describe(@A, @b);
并得到如下输出:
filename.m line 3: "A" is a 3x3 matrix
filename.m line 3: "b" is a scalar of value: 42
对于多个变量,如何打印:
- 调用函数的文件和行
- 姓名
- 类型
- 维度
您可以使用 size
来确定变量的大小,类型使用 class
,名称使用 inputname
。
例如:
function describe(a)
s = size(a); % Return the size of a
t = class(a); % Return the type of a
name = inputname(1); % Return the name of a
printf(['filename.m line 3: ''''' name ''''' size:' s(1) 'x' s(2) ' and type: ' t]);
end
我不知道如何使用文件名和行,如果你想用另一种方式显示它,你可以使用 if 条件将标量与向量与矩阵分开。
概述
在这个回答中,我列出了函数 describe
.
的 3 个细微不同的版本
- 获取任意数量的变量并创建输出字符串并使用
fpritnf
显示它
- 获取任意数量的变量并创建输出 元胞数组 并使用
disp
显示它
- 采用任意数量的变量 names 并创建一个输出字符串,如 1 中所示。这具有能够处理索引的优点,如
describe('myvar{1}')
.
主要功能描述和版本 1。
您可以使用各种标准函数来获取您想要的信息:
varargin
接受可变数量的输入变量
dbstack
获取文件名/当前行
inputname
获取传递给 describe
的输入的名称
fprintf
换行符显示
varargout
可选择 return 或显示结果
所以像这样创建你的 describe
函数:
function varargout = describe(varargin)
% varargin used to accomodate variable number of inputs
% By default, at least get functions stack (even if no variables are passed in)
st = dbstack;
% Convert cell output to string (excluding describe.m itself)
outstring = '';
% Loop backwards for more logical order (most recent last)
for ii = size(st, 1):-1:2
% new line character at end only works with fprintf, not disp
outstring = [outstring, st(ii).file, ' > ', st(ii).name, ...
', line ', num2str(st(ii).line), '\n'];
end
% Loop over variables and get info
for n = 1:nargin
% Use inputname to get name of input variables
outstring = [outstring, '"', inputname(n), '" is a ', ...
class(varargin{n}), ' of size ', mat2str(size(varargin{n})), '\n'];
end
% If output variable is requested then assign to output variable
% If not, just display output string to command window
if nargout
varargout{1} = outstring;
else
fprintf(outstring)
end
end
这里唯一需要的调整实际上是格式化,您需要的所有功能都在这里,希望内置足够的灵活性来满足您的需求。
示例输出:
% In myMainFunction.m, in the subfunction mySubFunction
% Could store output using 'd = describe(A,B);' and use 'fprintf' later
describe(A, B);
% In the command window
myMainFunction.m > myMainFunction, line 3
myMainFunction.m > mySubFunction, line 39
"A" is a double of size [1 3]
"B" is a double of size [1 5 9 7]
在 Matlab R2015b 中测试,根据文档,上面列出的所有函数自 R2006a 之前就已经存在,所以我认为它们很可能具有 Octave 等价物。
版本 2。
单元格而不是带有行分隔符的字符串。
这有一个不那么漂亮的输出,但也可能是一个不那么笨拙的方法,将字符串分配给一个元胞数组,而不是必须依赖 fprintf
换行。使用以下(为简洁起见未注释)版本可以轻松完成。
function varargout = describe(varargin)
st = dbstack; outcell = {};
for ii = size(st, 1):-1:2
outcell{end+1} = [st(ii).file, ' > ', st(ii).name, ', line ', num2str(st(ii).line)];
end
for n = 1:nargin
outcell{end+1} = ['"', inputname(n), '" is a ', class(varargin{n}), ' of size [', size(varargin{n}), ']'];
end
outcell = outcell.'; % Transpose to make it a column cell array
disp(outcell)
end
版本 3。
将变量 names 作为字符串传递,因此显示 'myvar(1)'
之类的内容。
这使用 evalin
来评估 caller
工作区中的变量(从中调用 describe
)。注意:当您在此 describe
函数中重新创建变量以获取其属性时,这可能会占用更多内存。
function varargout = describe(varargin)
% varargin used to accomodate variable number of input names
st = dbstack;
outstring = '';
for ii = size(st, 1):-1:2
outstring = [outstring, st(ii).file, ' > ', st(ii).name, ', line ', num2str(st(ii).line), '\n'];
end
% Loop over variables and get info
for n = 1:nargin
% Variables are passed by name, so check if they exist
try v = evalin('caller', varargin{n});
outstring = [outstring, '"', varargin{n}, '" is a ', class(v), ' of size ', mat2str(size(v)), '\n'];
catch
outstring = [outstring, 'Variable "', varargin{n}, '" not found!\n'];
end
end
fprintf(outstring)
end
使用示例:
% This can be used with indexed variables too. MUST PASS STRINGS!
describe('C{1}', 'B(1:2, :)')
% In the command window
myMainFunction.m > myMainFunction, line 3
myMainFunction.m > mySubFunction, line 39
"C{1}" is a double of size [1 3]
"B(1:2, :)" is a double of size [2 5]
% Because you're passing strings, you can use command syntax if you want
% Gives same result but don't have to pass strings
% as that's how inputs are interpreted anyway for command syntax.
describe C{1} B(1:2, :)
我自己也用类似的东西。这是我的:
function describe(A)
fprintf(' Class : %s\n',class(A));
fprintf(' Num. Elems : %s\n',num2str(numel(A)));
fprintf(' Size : %s\n',num2str(size(A)));
fprintf(' Total Min : %s\n',num2str(min (A(:))));
fprintf(' Total Max : %s\n',num2str(max (A(:))));
fprintf(' Total Sum : %s\n',num2str(sum (A(:))));
fprintf(' Total Mean : %s\n',num2str(mean(A(:))));
fprintf('Total St.Dev : %s\n',num2str(std (A(:), 1)));
fprintf(' Unique vals : %s\n',num2str(length(unique(A))));
end
编辑: 我知道这不是对您所问问题的字面答案,但我一直在使用它并认为它可能对分享有用。 :)
PS。话虽如此,我从来没有想过我可能想以非交互方式使用这样的函数:如果我需要以这种方式检查变量,我只需放置一个断点(或 keyboard
指令) 在代码中然后检查终端中最相关的内容,因此我从未想过要手动报告文件名和行号!您需要像这样执行非交互式调试的用例是什么?如果它是为了 post-mortem "testing" 目的,那么无论如何你真的应该编写适当的测试和完整性检查!
此外,这仅适用于单个变量,但我觉得更可取;如果你想要更多,这是一个非常简单的单行循环。
要调试我的 Octave/MATLAB 代码,我希望能够执行如下操作:
A = magic(3);
b = 42;
describe(@A, @b);
并得到如下输出:
filename.m line 3: "A" is a 3x3 matrix
filename.m line 3: "b" is a scalar of value: 42
对于多个变量,如何打印:
- 调用函数的文件和行
- 姓名
- 类型
- 维度
您可以使用 size
来确定变量的大小,类型使用 class
,名称使用 inputname
。
例如:
function describe(a)
s = size(a); % Return the size of a
t = class(a); % Return the type of a
name = inputname(1); % Return the name of a
printf(['filename.m line 3: ''''' name ''''' size:' s(1) 'x' s(2) ' and type: ' t]);
end
我不知道如何使用文件名和行,如果你想用另一种方式显示它,你可以使用 if 条件将标量与向量与矩阵分开。
概述
在这个回答中,我列出了函数 describe
.
- 获取任意数量的变量并创建输出字符串并使用
fpritnf
显示它
- 获取任意数量的变量并创建输出 元胞数组 并使用
disp
显示它
- 采用任意数量的变量 names 并创建一个输出字符串,如 1 中所示。这具有能够处理索引的优点,如
describe('myvar{1}')
.
主要功能描述和版本 1。
您可以使用各种标准函数来获取您想要的信息:
varargin
接受可变数量的输入变量dbstack
获取文件名/当前行inputname
获取传递给describe
的输入的名称
fprintf
换行符显示varargout
可选择 return 或显示结果
所以像这样创建你的 describe
函数:
function varargout = describe(varargin)
% varargin used to accomodate variable number of inputs
% By default, at least get functions stack (even if no variables are passed in)
st = dbstack;
% Convert cell output to string (excluding describe.m itself)
outstring = '';
% Loop backwards for more logical order (most recent last)
for ii = size(st, 1):-1:2
% new line character at end only works with fprintf, not disp
outstring = [outstring, st(ii).file, ' > ', st(ii).name, ...
', line ', num2str(st(ii).line), '\n'];
end
% Loop over variables and get info
for n = 1:nargin
% Use inputname to get name of input variables
outstring = [outstring, '"', inputname(n), '" is a ', ...
class(varargin{n}), ' of size ', mat2str(size(varargin{n})), '\n'];
end
% If output variable is requested then assign to output variable
% If not, just display output string to command window
if nargout
varargout{1} = outstring;
else
fprintf(outstring)
end
end
这里唯一需要的调整实际上是格式化,您需要的所有功能都在这里,希望内置足够的灵活性来满足您的需求。
示例输出:
% In myMainFunction.m, in the subfunction mySubFunction
% Could store output using 'd = describe(A,B);' and use 'fprintf' later
describe(A, B);
% In the command window
myMainFunction.m > myMainFunction, line 3
myMainFunction.m > mySubFunction, line 39
"A" is a double of size [1 3]
"B" is a double of size [1 5 9 7]
在 Matlab R2015b 中测试,根据文档,上面列出的所有函数自 R2006a 之前就已经存在,所以我认为它们很可能具有 Octave 等价物。
版本 2。
单元格而不是带有行分隔符的字符串。
这有一个不那么漂亮的输出,但也可能是一个不那么笨拙的方法,将字符串分配给一个元胞数组,而不是必须依赖 fprintf
换行。使用以下(为简洁起见未注释)版本可以轻松完成。
function varargout = describe(varargin)
st = dbstack; outcell = {};
for ii = size(st, 1):-1:2
outcell{end+1} = [st(ii).file, ' > ', st(ii).name, ', line ', num2str(st(ii).line)];
end
for n = 1:nargin
outcell{end+1} = ['"', inputname(n), '" is a ', class(varargin{n}), ' of size [', size(varargin{n}), ']'];
end
outcell = outcell.'; % Transpose to make it a column cell array
disp(outcell)
end
版本 3。
将变量 names 作为字符串传递,因此显示 'myvar(1)'
之类的内容。
这使用 evalin
来评估 caller
工作区中的变量(从中调用 describe
)。注意:当您在此 describe
函数中重新创建变量以获取其属性时,这可能会占用更多内存。
function varargout = describe(varargin)
% varargin used to accomodate variable number of input names
st = dbstack;
outstring = '';
for ii = size(st, 1):-1:2
outstring = [outstring, st(ii).file, ' > ', st(ii).name, ', line ', num2str(st(ii).line), '\n'];
end
% Loop over variables and get info
for n = 1:nargin
% Variables are passed by name, so check if they exist
try v = evalin('caller', varargin{n});
outstring = [outstring, '"', varargin{n}, '" is a ', class(v), ' of size ', mat2str(size(v)), '\n'];
catch
outstring = [outstring, 'Variable "', varargin{n}, '" not found!\n'];
end
end
fprintf(outstring)
end
使用示例:
% This can be used with indexed variables too. MUST PASS STRINGS!
describe('C{1}', 'B(1:2, :)')
% In the command window
myMainFunction.m > myMainFunction, line 3
myMainFunction.m > mySubFunction, line 39
"C{1}" is a double of size [1 3]
"B(1:2, :)" is a double of size [2 5]
% Because you're passing strings, you can use command syntax if you want
% Gives same result but don't have to pass strings
% as that's how inputs are interpreted anyway for command syntax.
describe C{1} B(1:2, :)
我自己也用类似的东西。这是我的:
function describe(A)
fprintf(' Class : %s\n',class(A));
fprintf(' Num. Elems : %s\n',num2str(numel(A)));
fprintf(' Size : %s\n',num2str(size(A)));
fprintf(' Total Min : %s\n',num2str(min (A(:))));
fprintf(' Total Max : %s\n',num2str(max (A(:))));
fprintf(' Total Sum : %s\n',num2str(sum (A(:))));
fprintf(' Total Mean : %s\n',num2str(mean(A(:))));
fprintf('Total St.Dev : %s\n',num2str(std (A(:), 1)));
fprintf(' Unique vals : %s\n',num2str(length(unique(A))));
end
编辑: 我知道这不是对您所问问题的字面答案,但我一直在使用它并认为它可能对分享有用。 :)
PS。话虽如此,我从来没有想过我可能想以非交互方式使用这样的函数:如果我需要以这种方式检查变量,我只需放置一个断点(或 keyboard
指令) 在代码中然后检查终端中最相关的内容,因此我从未想过要手动报告文件名和行号!您需要像这样执行非交互式调试的用例是什么?如果它是为了 post-mortem "testing" 目的,那么无论如何你真的应该编写适当的测试和完整性检查!
此外,这仅适用于单个变量,但我觉得更可取;如果你想要更多,这是一个非常简单的单行循环。