查看原文
其他

MATLAB程序设计语言(2.1)---变量的作用域

洞穴之外之编程哥 理念世界的影子 2021-06-23

公众号:理念世界的影子

文不可无观点,观点不可无论据。

转载请注明出处



MATLAB功能强大,编程方便,是国际广泛使用的计算软件。目前已有很多书籍介绍其在工程上的应用,但很少有从程序设计语言的角度写的书或文章。


MATLAB准备写一个系列,50~100篇左右。内容是笔者的心得,追求市面的书上没有的,都是有小程序作为案例的。上一篇阅读量极少,有没有可能是内容较多,程序较多,让人烦躁?补充这篇算是补救吧,采用短文章风格



MATLAB将变量存储在工作空间内(workspace),基工作空间(base workspace)保存MATLAB命令窗口或脚本中的变量。函数不使用基工作空间,每个函数有自己单独的工作空间,以实现数据的隔离保护。大多数情况下,MATLAB函数中的变量只能在函数中使用,而不能在其它函数和基工作空间使用,数据交互采用函数参数传递形式。


全局变量


global:global将变量申明为全局变量,注意的是,1)变量的申明必须在赋值前;2)全局变量在被引用前,需再次使用global声明。

persistent:persistent是一种特殊的全局变量,它仅对本很函数可见。运行下述函数多次,可发现其返回值每次递减。本命令类似于C语言下的static命令,值得注意的是,其初始化方法与C语言不同(static a=3;),而且此变量可以被clear functions命令(functions指具体的函数名)清除,除非在函数内增加mlock命令。


1   functionvariablescope

2   persistenta;

3   if(isempty(a)) a=3;end

4   a=a-1;

5   disp(a);



引用父(或基)工作空间


1   v = evalin('base''var');


其中evalin的第一个参数可以为’base’或’caller’,分别指基和父工作空间。


对基工作空间或父工作空间幅值


1   assignin('base''a', -1);


也可以使用:


1   evalin('base', 'a=-1;');


外部文件交换


采用外部文件交换可以跨越所有空间,在MATLAB内,save函数用于将本空间变量保存到文件中,load用于将变量导入本函数。


闭包


嵌套函数和匿名函数提供了一种称为闭包的能力。如下ode45的第一个参数为函数名,一般传入时间和自变量x,但有时需要传入更多的参数,这时可以使用λ函数(匿名函数)


1   ode45(@(t, x, a) fun(t, x, a), tspan, x0, a)


值得注意的是,对于下述程序


1  a=3; b=@() a; b(), a=4; b()


其返回值均为3,这是因为b函数本身包括了被声明当时所处的环境,当外界环境改变时,它仍保留了当时的环境,这种保留当时环境的特性被称为闭包,它带来了一系列编程特性,将在讲函数型数据时详述。


自省


MATLAB变量大部分表现与C语言相同,但其实现机制完全不同。C语言运行时,对变量的引用只表现为地址的指针的引用,其源程序中的名称已完全消失。在MATLAB中,当对变量赋值时,变量存在一个标签,从而也多出了更多的自省的机制。


直接运行whos命令,可以打印所有的变量。如下命令将工作空间内所有变量压缩到一个结构体内:


1  a=whos; cellfun(@(s) evalin('caller', sprintf('W.%s=%s;',s,s)), {a.name});


如下命令查看某个变量是否存在:exist('want_known', 'var');

如下命令查看函数中输入或输出参数有几个:nargin, nargout

如下命令传入函数的可变输入或输出参数:vargin, vargout

如下命令查看父函数名称:mfilename, dbstack

如下命令查看函数参数传入时的真实名称:inputname, dbstack


例如vargin, vargout可以这样使用


matlab不支持a=b=c=d=e=f=g=1的赋值,一个一个赋值太麻烦,这时可以采用逗号分隔符

1   [a b c d e f g]=deal(1, 1, 1, 1, 1, 1, 1)


或写为

1   [a b c d e f g]=deal(1)


deal函数代码如下


deal.m, MATLAB自带程序, edit deal即可看到


1   functionvarargout = deal(varargin)

2   ifnargin==1,

3     varargout = varargin(ones(1,nargout));

4       else

5         ifnargout ~= nargin

6           error('MATLAB:deal:narginNargoutMismatch',...

7                 'The number of outputs should match the number of inputs.')

8         end

9         varargout = varargin;

10       end


又如下述例子利用了跨域赋值和自省功能,可以在不返回值的情况下交换两输入参数


1       functionexchangevar (a, b)

2       交换ab变量的值

3       assignin('caller', inputname(1), b);

4       assignin('caller', inputname(2), a);


尽管MATLAB提供了更为丰富和方便的作用域控制功能,但编程序时并不建议使用。它使得函数逻辑复杂,程序更容易出错,调试更为困难,而且对于同一程序的同一形参,多次运行可能出现不同的返回值。在程序设计时常会追求一种引用透明性,即对同一程序同一形参的多次使用返回值均相同。这种理念引申出了一种不同于面向过程、面向对象的编程范式,称之为函数式编程,也将在后续介绍。函数式编程大家不一定要用,但学习后,对提高编程能力有所益处。





往期文章:

MATLAB

MATLAB程序设计语言(1)---入门

MATLAB程序设计语言(2)---help的see also与六度空间理论


微信扫一扫

关注“理念世界的影子”

版权声明:

本文是"洞穴之外"作者原创文章,欢迎转载,须署名并注明来自“理念世界的影子”公众号。

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存