MATLAB 函数(二)


概述

尽可能趁有空更一次的 MATLAB 笔记。

这次内容讲讲 MATALB 中的函数的高级部分。

  • MATLAB 函数的原理:使用函数的好处在于简化了代码同时增加了代码的可读性。但是在使用函数的时候可能会有一些有偏差的理解,因此需要从机器的尺度上取解释 MATLAB 函数的原理。
  • MATLAB 可选参数:同一个可能要求不同的使用方法,如果逐一编写单独的函数实现不仅浪费而且难以使用,因此调用函数的使用要能够自适应不同的输入参数和输出参数。
  • MATLAB 函数的其他类型:MATLAB 官方定义 MATLAB 函数有四种其他类型:匿名函数、局部函数、嵌套函数和私有函数。(私以为前两种可能更常用)

MATLAB 函数的原理

对于某一个 MATLAB 函数而言,它就像一个黑盒子(Black Box),用户只需要知道函数的用途而不必知道函数内部是怎么实现的。在主程序调用函数时,计算机开辟另一块内存空间,进入函数内部,运行函数命令,函数运行结束后,系统自动将这块内存空间回收,除了输出参数以外的所有函数内容都不再存在。

请务必记得:在函数内部做的一切不会对外部造成任何影响。

以下方这个函数为例

function add_1(x)
    x = x + 1;
    disp(['In function: x = ' num2str(x)]);
end

运行如下命令

x = 1;
add_1(x); % 在函数内部,x 的值被修改了
disp(['In main: x = ' num2str(x)]); % 主程序的 x 并没有被修改

结果得到

In function: x = 2
In main: x = 1

这又是什么情况呢?事实上,两个 x 是不同的值(函数并不执行“手递手式”地传递参数,而是将原来的变量拷贝一份放进函数的内存空间中),因此修改了函数内部的 x 后,在函数结束时就被回收,而外部的 x 并没有受到任何影响。

你可以将主程序的 x 替换成 a ,并在函数内部的“x = x + 1;”添加断点(只需单击每一行最左侧行号后的区域,即显示一个红色的断点;再次单击可以取消断点)。运行时,会在函数内部暂停,观察 Workspace 可以发现函数内部的 x = 1。点击工具栏中的 Continue 则可以继续运行看到主程序仍然是 a = 1。

a = 1;
add_1(a); % 在函数内部,x 的值被修改了
disp(['In main: a = ' num2str(a)]); % 主程序的 a 并没有被修改

由此可见,函数内部的变量在主程序中是“看不见”,函数内部无法使用主程序中的变量,同样地,主程序也无法使用函数内部的变量。因此,函数与主程序的“交流”就依赖于输入参数和输出参数。

将函数需要使用的变量传入,将函数计算所得结果传出。

MATLAB 可选参数

MATLAB 中的许多函数都有着各种灵活的输入方式,可以支持不同数量的输入参数和输出参数,比如常用的 zeros 函数就可以根据不同数量的输入参数创建不同维度的零矩阵。这种灵活性就基于 MATLAB 函数中的可选参数。

MATLAB 提供的可选参数有如下:

  • nargin 函数输入参数数目
  • nargout 函数输出参数数目
  • varargin 可变长度输入参数列表
  • varargout 可变长度的输出参数列表
  • narginchk 验证输入参数数目
  • nargoutchk 验证输出参数数目
  • validateattributes 检查数组的有效性
  • validatestring 检查文本的有效性
  • inputParser 函数的输入解析器
  • inputname 函数输入的变量名称
  • mfilename 当前正在运行的代码的文件名

样例一:对于不同输入参数执行不同操作

有时候对于一个函数希望有多种的调用方式时,使用可选参数 nargin。同理对于不同的输出参数采用不同的调用方式时,使用可选参数 nargout。

function report_name_id(name,id)
    switch nargin % 在函数中 nargin 就是调用函数时输入参数的数量
        case 2
            disp(['name: ' name ' id:' num2str(id)]); 
            % 两个输入参数时输出名字和 id
        case 1
            disp(['name: ' name ' without id information.']);
            % 仅输入一个参数名字(就是第一个参数)时输出名字和 无 id 信息
        otherwise
            disp('null');
            % 不给输入参数时,输出 null。
    end
end

执行以下命令

report_name_id('Tom',153412); % 两个输入参数时输出名字和 id
report_name_id('Tom'); % 输出名字和 无 id 信息
report_name_id(); % 输出 null

样例二:对于未知数量参数执行不同操作

有时候调用函数甚至不知道有多少个输入参数时,又该如何处置呢?这时就可以使用 varargin 来接收任意个输入参数,通过 varargin{index)}来访问对应的输入参数。

function information_items(name,varargin)
    disp(name);
    for index = 1:nargin-1
        disp(varargin{index});
    end
end

三种调用方式会导致不同的结果,可以看到 varargin 都可以将多余的任意数量个参数都取得,并且可以通过 varargin{index}来访问。(事实上,varargin 是一个 cell 型变量)

information_items('Tom','height:180','weight:72kg','age:17');
information_items('Jack','height:169','weight:74kg');
information_items('Bill','height:171','weight:88kg','age:23','shcool:Stanford');

同理,也可以对应地向 varargout{index} 赋值,将任意数量个输出参数传出。

样例三:验证输入参数数目

narginchk 是基于给定的输入参数上下限来验证输入参数是否符合要求的命令。

function two_or_three_inputs(varargin)
    narginchk(2,3);
    disp('There are two or three inputs');
end

同样使用三种调用方式

two_or_three_inputs(1); % 报错 error,输入参数不够
two_or_three_inputs(1,1);
two_or_three_inputs(1,1,1,1); % 报错 error,输入参数过多

同理也可以使用 nargoutchk 对输出参数验证,此外,不妨尝试自己使用 error 函数给出合适的调用函数提示信息。

样例四:函数输入的变量名称

你可能会想函数输入的变量名称肯定是已知的,为什么还要特地设计这样一个函数呢?这个函数是有一定作用的。

function y = data_to_string(varargin)
    y = [];
    for index = 1:nargin
        y = [y inputname(index) ':' varargin{index} ';'];
    end
end

这个函数可以将数据根据对应的变量类型串成一个数据包。

name = 'Tom';
age = '18';
height = '180cm';
weight = '70kg';
str = data_to_string(name,age,height,weight);

MATLAB 函数其他类型

MATLAB 官方确定的其他类型的函数包括四种:

  • 匿名函数
  • 局部函数
  • 嵌套函数
  • 私有函数

匿名函数

匿名函数是仅包含一句 MATLAB 命令的函数。匿名函数的优点在于无需另外创建保存一个 m 文件,甚至可以在脚本文件和命令行中随时定义随时使用。形如下式的命令可以创建一个匿名函数:

fun = @(x,y)x.^2+y.^2-2*x*y+4;

其中 fun 是函数句柄,@ 运算符则用于创建一个句柄。

局部函数

局部函数也叫做子函数,相当于某个完整函数的附属函数。局部函数编写于某个函数最后一行之后,是该函数的附属函数。这意味着局部函数使用范围有限:仅能被同一个文件中的其他函数调用,对其他函数和命令行不可见。

function [avg, med] = mystats(x)
% 主函数 可以被外部检索调用
n = length(x);
avg = mymean(x,n);
med = mymedian(x,n);
end

function a = mymean(v,n)
% 子函数 1 
% 只能被主函数和其他子函数调用
a = sum(v)/n;
end

function m = mymedian(v,n)
% 子函数 2
% 只能被主函数和其他子函数调用
w = sort(v);
if rem(n,2) == 1
    m = w((n + 1)/2);
else
    m = (w(n/2) + w(n/2 + 1))/2;
end
end

特别地,如果你习惯省略函数体结尾的 end,在同一个文件中应当保证子函数和主函数使用同一种格式。

嵌套函数

嵌套函数是定义在函数中的函数,外层函数可以调用内层函数并且如果内层函数变量在外层函数中有定义,那么嵌套函数可以访问和修改在其父函数中定义的变量。

function main1
x = 5;
nestfun1

   function nestfun1 
     x = x + 1;
   end 

end

私有函数

假设当前工作路径为 “/xxx”,在文件夹 xxx 创建一个名为“private”子文件夹,可以指定一个函数为私有函数。这样一来,只有文件夹 xxx下的函数可以调用这个私有函数。

小结

到此函数的内容也告一段落,本文除了 MATLAB 函数的内容外,还有一个额外的点就是断点调试(快速地中断和保留中断时的变量,能够让你加快调试的步骤)。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,298评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,701评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,078评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,687评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,018评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,410评论 1 211
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,729评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,412评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,124评论 1 239
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,379评论 2 242
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,903评论 1 257
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,268评论 2 251
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,894评论 3 233
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,014评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,770评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,435评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,312评论 2 260

推荐阅读更多精彩内容