Skip to content

MATLAB - 函数

函数是任何非简单程序的构建块。在 MATLAB 中,它们对于创建可重用、模块化和可读的代码至关重要。函数封装了一个任务,在自己的独立工作区中操作,并通过输入和输出参数与其他代码通信。

一个现代的 MATLAB 函数,保存在其独立的 .m 文件中,应包含清晰的签名、帮助文本和健壮的输入验证。

function [stat1, stat2] = computeStats(data, options)
%COMPUTESTATS 计算输入数据的均值和标准差。
% [M, S] = COMPUTESTATS(DATA) 计算向量 DATA 的均值 M 和标准差 S。
%
% [...] = COMPUTESTATS(..., 'Dimension', DIM) 沿维度 DIM 操作。
% [...] = COMPUTESTATS(..., 'RemoveNaNs', true) 在计算前移除 NaN 值。
% computation。
arguments
data (:,:) {mustBeNumeric, mustBeReal}
options.Dimension (1,1) {mustBeInteger} = 1
options.RemoveNaNs (1,1) {mustBeNumericOrLogical} = false
end
% 函数体从这里开始
if options.RemoveNaNs
data = data(~isnan(data));
end
stat1 = mean(data, options.Dimension);
stat2 = std(data, 0, options.Dimension); % 0 表示默认归一化
end % 函数结束

这种现代结构的关键组成部分包括:

  • 函数签名(Function Signature):function [out1, ...] = functionName(in1, ...) 定义输入和输出。
  • 帮助文本(Help Text):签名后连续的注释块,当您键入 help functionName 时会显示。它对文档编写至关重要。
  • arguments 块(arguments block):(R2019b+) 一种声明性方式,用于定义输入参数、它们的类型、大小和默认值。它取代了旧的、使用 nargin 和 inputParser 进行手动解析的方法。

匿名函数是简单的单行函数,无需单独的 .m 文件即可定义。它们对于将函数作为参数传递给另一个函数(例如,用于积分或优化)非常有用。

% 语法: fhandle = @(arglist) expression
% 示例 1:一个简单的幂函数
powerFunc = @(x, n) x.^n;
result = powerFunc(5, 2) % result = 25
% 示例 2:将匿名函数与 'integral' 配合使用
% 计算 x^2 从 0 到 1 的积分
quadratic = @(x) x.^2;
area = integral(quadratic, 0, 1);

您可以在单个 .m 文件中包含多个函数。第一个函数是主函数(其名称与文件相同),可以从外部调用。所有其他函数都是局部函数(以前称为子函数),并且仅对同一文件中的其他函数可见。这是将复杂任务分解为更小、更易于管理的辅助函数的绝佳方式。

% 在名为 'mainTask.m' 的文件中
function result = mainTask(inputVal)
% 这是主函数
intermediate = helperA(inputVal);
result = helperB(intermediate);
end
function out = helperA(in)
% 这是一个局部函数,只能由 mainTask 和 helperB 调用
out = in * 2;
end
function out = helperB(in)
% 这是另一个局部函数
out = in + 5;
end

自 R2016b 起,您还可以在脚本文件中定义局部函数,这对于自包含的示例和任务非常方便。

嵌套函数完全定义在另一个函数内部。它的主要特点是共享其父函数的工作区,允许它访问和修改父函数的变量,而无需将它们作为参数传递。这对于创建具有持久状态的函数非常有用。

若要在多个主函数之间共享辅助函数,但不将其全局暴露,请将它们放在名为 private 的子文件夹中。此文件夹中的函数只能由紧邻父文件夹中的函数调用。这是代码封装和创建库的强大工具。

虽然 MATLAB 支持可以从任何函数访问的 global 变量,但在现代编程中强烈不推荐使用它们。全局变量使代码难以调试、维护和理解,因为不清楚变量在哪里被修改。始终优先通过函数参数显式传递数据。 如果您需要管理共享状态,请考虑使用类或嵌套函数结构。

  • 一任务一函数:每个函数都应有一个单一、明确的目的。
  • 使用 arguments 块:对于 R2019b 或更高版本编写的任何函数,使用 arguments 块进行输入验证。它更健壮且可读性更强。
  • 编写帮助文本:未来的您(和您的同事)会感谢您。良好的文档与代码本身同样重要。
  • 测试您的函数:使用 MATLAB 单元测试框架为您的函数创建自动化测试。这可确保它们正常工作,并防止在您进行更改时出现回归(buildtest 命令或测试浏览器 UI)。
  • 使用项目组织:对于大型应用程序,使用 MATLAB 项目(.prj 文件)以结构化方式管理文件、路径和依赖项。