MATLAB函数编程入门:从脚本到函数的进阶指南

MATLAB函数编程入门:从脚本到函数的进阶指南 1. 项目概述为什么函数是MATLAB的灵魂如果你刚接触MATLAB可能觉得它就是个高级计算器点点鼠标输输公式。但当你真正用它来解决数学建模、数据分析或者图像处理这类稍微复杂一点的问题时很快就会发现把几百行代码全堆在一个脚本文件里简直就是一场灾难。代码混乱、调试困难、重复劳动……这时候函数Function就登场了它可以说是MATLAB从“玩具”升级为“生产力工具”的关键一步。简单来说函数就是一段封装好的、可以重复使用的代码块。你给它一个输入或者不给它经过内部处理给你一个输出或者没有。这听起来平平无奇但它的威力巨大。想象一下你在做一个复杂的模型其中需要反复计算某个特定公式比如一个自定义的滤波器或者一个复杂的物理方程。如果没有函数你就得把这个公式的代码复制粘贴几十遍。一旦公式需要修改你就得把所有粘贴过的地方都改一遍不仅效率低下还极易出错。而有了函数你只需要在一个地方定义好它然后在任何需要的地方“调用”它。修改也只需改函数定义那一处所有调用它的地方自动生效。从“数学建模速成”和“零基础入门”的角度看掌握函数是跳出新手村、写出规范、可维护代码的必经之路。很多同学在入门时只学脚本Script写出来的代码往往冗长且难以复用。本教程的目标就是在两小时内让你彻底理解如何在MATLAB中定义和调用函数并体会到它带来的结构化编程的便利。这不仅是为了完成作业更是为了培养一种良好的编程习惯让你在后续更复杂的项目中不至于手忙脚乱。2. 核心概念解析脚本与函数的本质区别在深入函数之前我们必须先厘清MATLAB中两种基本的文件类型脚本文件.m文件和函数文件.m文件。它们文件扩展名都是.m但行为天差地别。理解这个区别是正确使用函数的前提。2.1 脚本文件共享的工作空间脚本文件是最简单的程序单元。你可以把它看作是一系列MATLAB命令的记事本。当你运行一个脚本时MATLAB会逐行执行其中的命令而且脚本中的所有变量都会存储在当前的基础工作区Base Workspace中。举个例子你创建一个my_script.m文件内容如下% my_script.m a 5; b 10; sum_ab a b; disp(sum_ab);在命令窗口运行my_script后变量a、b、sum_ab都会出现在你的工作区窗口里。后续你在命令窗口直接输入a也能得到5。这种共享性很方便但也非常危险。如果另一个脚本也使用了同名变量a就会互相覆盖导致难以预料的错误。脚本适合执行一系列简单的、线性的任务或者作为一次性分析的顶层文件。2.2 函数文件独立的黑盒子函数文件则是一个独立的模块。它的核心特征是拥有自己独立的局部工作空间。函数内部定义的变量与基础工作区以及其他函数的变量是隔离的除非使用特殊声明。函数通过输入参数接收数据通过输出参数返回结果内部实现细节对调用者来说是隐藏的——这就是所谓的“黑盒子”模型。一个最基本的函数文件my_function.m其结构如下function output my_function(input) % MY_FUNCTION 这里是函数的帮助文档简要说明功能 % 详细描述函数做了什么输入输出是什么 % 例如output my_function(input) 计算输入值的平方。 % 函数体具体的计算过程 output input ^ 2; end当你调用result my_function(4)时数字4被传递给函数内部的input函数计算input^2得到16并将其赋值给output最终output的值16被返回给调用者存储在变量result中。关键在于函数内部的input和output变量在函数执行完毕后就被清除了不会污染你的基础工作区。这种封装性使得代码更安全、更模块化。注意函数文件名必须与文件中的第一个函数名即主函数名完全一致。例如上面这个函数必须保存为my_function.m保存为calculate.m或别的名字将无法直接调用。2.3 对比表格一目了然的区别为了更清晰地展示我们可以用一个表格来对比特性脚本文件 (.m)函数文件 (.m)第一行没有固定格式通常以注释开始。必须以function关键字开头的函数定义行。工作空间共享基础工作区变量全局可见。拥有独立的局部工作空间变量隔离。数据传递直接操作工作区中的变量。通过输入参数Input Arguments传入通过输出参数Output Arguments传出。代码复用差代码复制粘贴导致冗余。优一次定义多处调用。适用场景简单的顺序执行、一次性分析、项目主流程控制。封装特定功能、复杂计算模块、可复用工具。实操心得一个良好的MATLAB项目结构通常是顶层有一个或多个脚本文件作为“主程序”负责组织流程、准备数据、调用各种函数而具体的计算、绘图、分析等任务都被封装成一个个独立的函数。这样你的代码会变得非常清晰就像搭积木一样。3. 函数定义详解从语法到实战了解了函数是什么接下来我们亲手创建几个。函数定义看似简单但细节决定成败。3.1 基本语法结构拆解一个标准的函数定义包含以下几个部分我们逐行解析function [out1, out2, ...] functionName(in1, in2, ...) % FUNCTIONNAME 函数功能简述 % [out1, out2] FUNCTIONNAME(in1, in2) 详细描述函数功能 % 并说明每个输入参数和输出参数的意义。 % % 示例 % [area, circumference] circleCalc(5) % % 输入参数 % in1 - 对第一个输入参数的描述 % in2 - 对第二个输入参数的描述可选 % % 输出参数 % out1 - 对第一个输出参数的描述 % out2 - 对第二个输出参数的描述可选 % % 参见 also OTHER_FUNCTION % 函数体这里是实现具体功能的MATLAB代码 % 可以使用in1, in2等输入参数 % 必须对out1, out2等输出参数进行赋值 out1 ... % 某种基于输入的计算 out2 ... % 另一种计算 end函数定义行function [out1, out2, ...] functionName(in1, in2, ...)function关键字声明这是一个函数。[out1, out2, ...]输出参数列表用方括号括起来。如果只有一个输出可以省略方括号写成function out1 functionName(...)。如果没有输出可以写为空方括号[]或者直接省略如function functionName(...)。functionName函数名命名规则与变量名相同字母开头由字母、数字、下划线组成。务必与文件名一致。(in1, in2, ...)输入参数列表用圆括号括起来。如果没有输入也需要保留空括号()。帮助文档注释H1 Line及后续紧接着定义行下的注释块。这是函数的“名片”极其重要。第一行H1 Line% FUNCTIONNAME 函数功能简述。这一行会被help functionName命令和lookfor命令搜索到。务必简洁明了地概括函数功能。详细描述后续的注释行详细说明用法、输入输出参数含义、示例等。良好的文档能让你和你的合作者在几个月后还能快速理解这段代码的用途。函数体实现功能的核心代码区域。在这里你可以使用输入参数定义局部变量进行计算并最终为输出参数赋值。end关键字在较新版本的MATLAB中对于只包含一个函数的文件end是可选的。但对于包含嵌套函数或局部函数的文件end是必须的。我的强烈建议是始终加上end。这能使代码结构更清晰并与大多数编程语言的习惯保持一致避免不必要的混淆。3.2 四种常见函数类型实战下面我们通过四个具体例子覆盖最常见的函数使用场景。类型一无输入无输出函数这种函数通常用于执行一个固定的任务比如显示菜单、初始化环境或绘制一个标准图形。function plotDefaultSine() % PLOTDEFAULTSINE 绘制一个默认的正弦函数曲线 % 此函数无需输入直接绘制 x 从 0 到 2*pi 的 sin(x) 曲线。 x 0:0.01:2*pi; % 在函数内部生成数据 y sin(x); figure; % 新建一个图形窗口 plot(x, y, b-, LineWidth, 2); title(Default Sine Wave); xlabel(x); ylabel(sin(x)); grid on; end调用方式直接在命令窗口输入plotDefaultSine()即可。类型二有输入无输出函数函数根据输入参数执行操作但不返回数据。常用于修改图形、保存文件等。function plotCustomSine(frequency, amplitude) % PLOTCUSTOMSINE 根据给定频率和振幅绘制正弦曲线 % plotCustomSine(freq, amp) % % 输入参数 % frequency - 正弦波的频率 % amplitude - 正弦波的振幅 x 0:0.01:2*pi; y amplitude * sin(frequency * x); % 使用输入参数 figure; plot(x, y, r--, LineWidth, 1.5); title(sprintf(Sine Wave: Freq%.1f, Amp%.1f, frequency, amplitude)); xlabel(x); ylabel(y); grid on; end调用方式plotCustomSine(2, 1.5)会绘制一个频率为2、振幅为1.5的正弦波。类型三无输入有输出函数函数生成并返回数据比如从硬件读取传感器数据、生成随机配置等。function [data, labels] generateDemoData() % GENERATEDEMODATA 生成用于演示的随机数据集 % [data, labels] GENERATEDEMODATA() % % 输出参数 % data - 一个 100x2 的矩阵包含二维数据点 % labels - 一个 100x1 的向量包含每个数据点的类别标签 (1 或 2) rng(default); % 固定随机种子确保每次生成的数据相同 data [randn(50,2)*0.5 1; randn(50,2)*0.5 - 1]; % 生成两类聚集的数据 labels [ones(50,1); 2*ones(50,1)]; % 前50个标签为1后50个为2 end调用方式[X, y] generateDemoData();之后变量X和y就可以用于后续的聚类或分类演示。类型四有输入有输出函数最常用这是函数的完全体接收输入进行处理返回结果。数学建模中的核心计算模块基本都是这种形式。function [mean_val, std_val] computeStats(data_vector) % COMPUTESTATS 计算数据向量的均值和标准差手动实现 % [mean_val, std_val] COMPUTESTATS(data_vector) % % 输入参数 % data_vector - 一个数值向量 % 输出参数 % mean_val - 向量的算术平均值 % std_val - 向量的样本标准差 % 输入检查良好的习惯 if ~isvector(data_vector) error(输入必须是一个向量。); end n length(data_vector); mean_val sum(data_vector) / n; % 计算均值 % 计算标准差sqrt( sum((x_i - mean)^2) / (n-1) ) std_val sqrt( sum((data_vector - mean_val).^2) / (n-1) ); end调用方式data [1, 2, 3, 4, 5]; [m, s] computeStats(data);会得到m3,s≈1.5811。注意事项在函数体内强烈建议对输入参数进行有效性检查如上面的isvector检查。这能避免因意外输入导致的诡异错误使你的函数更健壮。MATLAB内置的mean和std函数当然更高效但这里手动实现是为了展示函数内部的计算逻辑。3.3 函数保存与路径问题写好函数后保存文件时MATLAB会强制要求文件名与主函数名一致。如果你将上面的computeStats函数保存为myStats.m当你调用computeStats时MATLAB会报错“未定义函数或变量‘computeStats’”。要让MATLAB找到你的函数有几种方法保存在当前文件夹最简单的方式将函数文件放在你当前MATLAB工作路径指向的文件夹里。添加到搜索路径如果你希望在任何地方都能调用这个函数可以将其所在文件夹添加到MATLAB的搜索路径中。在主页标签页点击“设置路径”然后“添加文件夹”并选择你的函数文件夹即可。使用完整路径调用不推荐但可行如result C:\MyFunctions\computeStats(data)。实操心得我个人的习惯是为每一个项目建立一个独立的文件夹里面包含主脚本和所有相关的函数文件。这样项目是自包含的拷贝到任何地方都能运行不会因为路径问题出错。对于通用的工具函数我会专门建立一个MyToolboxes文件夹并将其永久添加到MATLAB搜索路径中。4. 函数调用与数据传递的深层机制知道怎么定义函数还要知道怎么正确地调用它以及数据是如何在调用者和函数之间传递的。这里面的细节是很多新手踩坑的地方。4.1 调用方式与参数匹配函数调用非常简单格式为[输出实参] 函数名(输入实参)。关键在于“实参”与“形参”的匹配。形参Formal Parameters函数定义行(in1, in2, ...)中的in1,in2是函数内部的变量名是“形式上的参数”。实参Actual Arguments调用函数时functionName(arg1, arg2, ...)中的arg1,arg2是具体的数值、变量或表达式是“实际的参数”。调用时MATLAB会将实参的值传递给对应的形参。这是一种“按值传递”Pass by Value。这意味着函数内部对形参的修改不会影响调用者环境中实参变量的值除非实参是句柄对象但这是进阶话题。% 定义函数 function y addOne(x) x x 1; % 修改形参 x y x; end % 调用函数 a 5; b addOne(a); % 实参 a 的值 5 传递给形参 x disp(a); % 输出 5a 的值没有改变 disp(b); % 输出 6得到的是函数返回的结果4.2 处理多个输入输出参数当输入输出参数较多时调用和定义都需要注意顺序。定义多参数函数function [pos, vel, energy] projectileMotion(v0, theta, t, g) % 计算抛射体运动给定初速v0角度theta(度)时间t重力加速度g返回位置、速度、动能。 theta_rad deg2rad(theta); pos v0 * cos(theta_rad) * t; % 水平位置 (简化仅计算x方向) vel v0 * cos(theta_rad); % 水平速度 (忽略空气阻力) energy 0.5 * (v0^2) - g * (v0 * sin(theta_rad) * t - 0.5 * g * t^2); % 机械能 end调用多参数函数 调用时必须按照定义时的顺序提供实参。% 正确的调用 [p, v, e] projectileMotion(50, 45, 2, 9.8); % 错误的调用参数顺序错误结果毫无意义 [p, v, e] projectileMotion(45, 50, 9.8, 2);选择性接收输出 MATLAB允许你只接收部分输出参数从左到右匹配。pos_only projectileMotion(50, 45, 2, 9.8); % 只接收第一个输出 [pos, vel] projectileMotion(50, 45, 2, 9.8); % 接收前两个输出 % [~, vel] ... 使用波浪线 ~ 忽略某个位置的输出使用波浪线~忽略不需要的输出是一个好习惯能明确表达你的意图。4.3 可变数量参数varargin 和 varargout这是MATLAB函数中非常灵活和强大的特性允许函数接受或返回任意数量的参数。这在编写通用工具函数时特别有用。vararginVariable-length input argument list作为最后一个输入参数它是一个元胞数组Cell Array包含了所有传入的额外输入参数。narginNumber of input arguments函数内部可用的变量表示调用时实际传入的输入参数个数。varargout和nargout对应输出原理类似。示例一个求平均值的函数可以接受多个向量function avg multiMean(varargin) % MULTIMEAN 计算多个向量的平均值 % avg MULTIMEAN(vec1, vec2, ..., vecN) 返回所有输入向量的平均值。 % 示例multiMean([1 2], [3 4 5], 6) 返回 (123456)/6 3.5 if nargin 0 error(至少需要提供一个输入参数。); end all_numbers []; for i 1:nargin % 将每个输入参数可能是标量、向量、矩阵转换并拼接 current_arg varargin{i}; if isnumeric(current_arg) all_numbers [all_numbers; current_arg(:)]; % 展开并拼接 else error(输入参数 %d 不是数值类型。, i); end end avg mean(all_numbers); end调用示例m1 multiMean([1, 2, 3]); % 输入一个向量 m2 multiMean(1, 2, 3, 4, 5); % 输入多个标量 m3 multiMean([1 2; 3 4], 5, [6 7 8]); % 混合输入实操心得varargin在编写绘图函数时尤其常见比如你想自定义一个绘图函数允许用户传入任意多的“属性-值”对如LineWidth, 2, Color, r就可以用varargin来捕获这些参数然后传递给内置的plot函数。掌握它能极大提升你编写通用代码的能力。5. 进阶技巧与最佳实践掌握了基础我们来看看如何让函数变得更强大、更专业。这些技巧能显著提升你的代码质量和开发效率。5.1 子函数与私有函数模块化组织一个.m文件里不仅可以包含一个主函数还可以包含多个仅供该文件内部调用的子函数Subfunction。子函数写在主函数之后共享主函数的变量空间这不同于独立的函数文件但只能被同一个文件内的函数调用。function [avg, med] statsWithHelper(data) % 主函数计算平均值和中位数 avg computeAverage(data); med computeMedian(data); end % --- 子函数 1计算平均值 --- function a computeAverage(x) a sum(x) / length(x); end % --- 子函数 2计算中位数 --- function m computeMedian(x) x_sorted sort(x); n length(x); if mod(n, 2) 1 % 奇数个 m x_sorted((n1)/2); else % 偶数个 m (x_sorted(n/2) x_sorted(n/21)) / 2; end end子函数有助于将复杂的函数分解成更小、更易管理的部分同时避免在全局命名空间中创建大量小函数文件。另一种组织方式是私有函数。在一个文件夹中创建一个名为private的子文件夹放在里面的函数只能被其父文件夹中的函数或脚本调用。这对于隐藏实现细节、提供内部工具函数非常有用。5.2 函数句柄将函数作为变量传递函数句柄Function Handle是一种特殊的数据类型它提供了对函数的间接引用。你可以像使用变量一样使用它并将其传递给其他函数。这在需要动态选择函数或实现回调机制时非常强大。创建函数句柄使用符号% 创建内置函数句柄 f_sin sin; % 创建自定义函数句柄假设 myFunc.m 已定义 f_my myFunc; % 创建匿名函数句柄见下一小节使用函数句柄调用函数x pi/4; result1 f_sin(x); % 等价于 sin(pi/4) result2 f_my(x); % 等价于 myFunc(pi/4)经典应用fplot和fzero% 绘制匿名函数定义的曲线 f (x) x.^2 - 2*x 1; fplot(f, [-5, 5]); title(Plot of f(x) x^2 - 2x 1); % 寻找函数的零点 fun (x) cos(x) - x; % 定义函数cos(x) - x 0 x_solution fzero(fun, 0.5); % 在0.5附近寻找零点 disp([解为 x , num2str(x_solution)]);这里fplot和fzero都是MATLAB内置的、接受函数句柄作为输入的函数。这种设计模式使得它们的通用性极强。5.3 匿名函数快速定义简单函数对于非常简短的、一次性的操作专门写一个.m文件太麻烦。匿名函数允许你在单行代码中定义一个函数。基本语法函数句柄 (输入参数列表) 表达式% 定义一个计算平方的匿名函数 square (x) x.^2; disp(square(5)); % 输出 25 % 定义两个变量的匿名函数 hypotenuse (a, b) sqrt(a.^2 b.^2); disp(hypotenuse(3, 4)); % 输出 5 % 直接在需要的地方使用例如在数组运算中 data [1, 2, 3, 4]; squared_data arrayfun((x) x^2, data); % 对每个元素应用匿名函数 disp(squared_data); % 输出 [1, 4, 9, 16]匿名函数非常适合于简单的数学变换、作为参数传递给像integral积分、fminsearch优化这样的高阶函数。注意事项匿名函数只能包含一个可执行的表达式。它不能包含多条语句、循环或条件判断复杂的逻辑需要借助其他方式。它的主要优势是简洁和“就地定义”。5.4 输入参数解析与验证inputParser当你的函数有多个可选参数或者需要对输入进行复杂的验证时手动写一堆if nargin 2 ...会非常繁琐且容易出错。MATLAB提供了强大的inputParser对象来优雅地处理这个问题。function result myAdvancedFunction(mandatoryArg, varargin) % MYADVANCEDFUNCTION 一个使用inputParser的示例函数 % result MYADVANCEDFUNCTION(req, Option1, val1, Option2, val2, ...) % % 必需参数 % req - 一个必需的数值参数 % % 可选参数对 % Mode - 模式选择fast 或 accurate (默认: fast) % Threshold - 阈值一个正数 (默认: 0.5) % Plot - 是否绘图true 或 false (默认: false) % 创建 inputParser 对象 p inputParser; % 添加必需参数 addRequired(p, RequiredArg, isnumeric); % 验证必须是数值 % 添加可选参数及其默认值、验证函数 addParameter(p, Mode, fast, (x) ismember(x, {fast, accurate})); addParameter(p, Threshold, 0.5, (x) isnumeric(x) x 0); addParameter(p, Plot, false, islogical); % 解析输入 parse(p, mandatoryArg, varargin{:}); % 提取解析后的参数值 req p.Results.RequiredArg; mode p.Results.Mode; threshold p.Results.Threshold; doPlot p.Results.Plot; % 以下是函数的主要逻辑使用解析后的参数 disp([必需参数, num2str(req)]); disp([模式, mode]); disp([阈值, num2str(threshold)]); disp([绘图, num2str(doPlot)]); % 模拟一些计算 if strcmp(mode, fast) result req * threshold; else result req / threshold; end if doPlot figure; plot([req, result], o-); title(计算结果); end end调用示例% 只提供必需参数使用所有默认选项 r1 myAdvancedFunction(10); % 提供部分可选参数 r2 myAdvancedFunction(10, Threshold, 0.8, Plot, true); % 提供所有可选参数顺序任意 r3 myAdvancedFunction(10, Plot, true, Mode, accurate, Threshold, 2);使用inputParser你的函数接口会变得非常清晰、健壮且用户友好。它自动处理了参数默认值、名称-值对匹配、输入验证和错误提示是编写专业级函数的必备工具。6. 调试、优化与常见问题排查即使理解了所有语法在实际编写和调用函数时也难免会遇到错误。掌握调试技巧和了解常见问题能帮你快速定位和解决bug。6.1 函数调试的基本方法设置断点在编辑器窗口中点击行号旁边的短横线“-”它会变成红色的圆点这就是断点。当运行代码执行到这一行时程序会暂停你可以查看当前工作空间的所有变量。步入Step In当程序在断点处暂停或你使用dbstop if error在出错时暂停后按F11或调试工具栏的“步入”按钮。如果下一行是函数调用你会进入该函数的内部进行调试。这是调试函数最核心的操作。步过Step Over按F10。执行当前行但如果当前行包含函数调用则不进入该函数内部直接得到该函数的结果。当你确信某个函数没问题时使用。步出Step Out按ShiftF11。执行完当前函数剩余的所有代码并返回到调用它的上一级函数。查看工作区在调试模式下工作区窗口会显示当前函数的局部变量这与平常的基础工作区不同。你可以清楚地看到输入参数的值、函数内部创建的变量。命令行调试在调试暂停时你可以在命令窗口直接输入命令来查看或修改变量值例如输入某个变量名查看其内容或者给变量赋新值。实操心得调试函数时我最常用的组合是先在怀疑有问题的函数调用行之前设置断点运行程序。暂停后使用F11步入函数内部然后结合F10单步执行观察每一步之后变量的变化是否符合预期。重点关注条件判断if、循环for/while的边界和函数返回return的地方。6.2 性能考量与向量化MATLAB是为矩阵运算设计的循环特别是多层循环往往很慢。在函数中应尽量使用向量化操作代替循环。低效的循环实现function y slowSquare(x) n length(x); y zeros(size(x)); for i 1:n y(i) x(i)^2; end end高效的向量化实现function y fastSquare(x) y x.^2; % 使用点乘方运算符 .^ 对整个向量进行操作 end对于大规模数据向量化操作可能带来成百上千倍的性能提升。在函数中养成向量化思维至关重要。6.3 常见错误与解决方案速查表下面列出一些定义和调用函数时最常见的错误及其解决方法错误信息/现象可能原因解决方案“未定义函数或变量 ‘xxx’”1. 函数文件名与函数名不一致。2. 函数文件不在MATLAB搜索路径或当前文件夹中。3. 拼写错误。1. 检查并确保文件名是xxx.m。2. 使用which xxx命令查看MATLAB能否找到该函数。将文件移到当前文件夹或添加路径。3. 仔细检查调用时的拼写。“输入参数的数目不足”调用函数时提供的输入参数少于函数定义要求的最少数量。检查函数定义确保提供了所有必需的参数。使用nargin在函数内部进行参数个数判断或使用inputParser设置默认值。“输出参数太多”调用函数时期望接收的输出参数个数多于函数实际能返回的个数。检查函数定义中输出参数的个数。在调用时使用波浪线~忽略不需要的输出或修改调用语句只请求函数能提供的输出数量。“索引超出数组范围”函数内部试图访问数组不存在的元素。常见于循环边界错误或对输入向量/矩阵维度的错误假设。在函数开始处添加输入验证如if ~isvector(data), error(...); end。使用size,length,numel获取数组实际维度。在循环中使用1:length(array)而非硬编码数字。函数修改了输入变量意外发现调用函数后传入的变量值改变了。牢记MATLAB默认“按值传递”。如果发生此情况检查函数内部是否对输入参数进行了赋值操作如in1 ...。除非使用句柄对象否则这不会影响外部变量。此现象可能源于混淆了变量名或者外部变量与函数内其他操作同名。“函数定义与脚本文件混淆”在脚本文件中使用了function关键字或者试图直接运行一个包含多个顶层函数的.m文件。确保一个独立的.m文件要么是纯脚本无function要么只包含一个主函数可附带子函数。要运行脚本直接输入文件名要调用函数需使用正确的参数语法。帮助文档不显示在命令窗口输入help functionName没有显示你写的注释。确保帮助文档注释是紧跟在函数定义行之后中间不能有空行。注释必须以%开头。一个典型的调试案例你写了一个函数processData(data, threshold)调用时却报错“索引超出范围”。你应该在函数第一行设置断点。调用函数程序暂停。步入函数内部检查输入参数data和threshold的值和维度是否如你所料。单步执行观察在哪一行代码发生了错误。通常是某行试图访问data(i)而i超出了data的长度。检查导致i值异常的循环或索引计算逻辑。最后再分享一个我个人的小技巧在开发复杂函数时我通常会先写一个简单的“测试脚本”Test Script在这个脚本里用各种典型的、边缘的输入去调用我的函数并验证输出是否正确。这其实就是单元测试的雏形能帮你提前发现很多逻辑错误尤其是在修改了函数之后运行一下测试脚本能快速确认功能是否正常。