- 引入
- 关于函数m文件,请注意以下几点:
- 7.2.1子函数
- 7.2.2 私有函数
- 7.2.3 P-code文件
- 7.2.4 使用Profiler工具来分析和优化M文件的性能
试试下面这个更一般的例子,它返回向量x中值的平均值和标准差。虽然有两个MATLAB函数可以做到这一点,但将它们组合成一个是有用的。编写一个函数文件:
讯享网
这段代码是一个名为 的函数,用于计算数据向量 的均值和标准差。
-
:这是函数定义行,声明了函数名为 ,输入参数为 ,输出参数为 和 。它告诉 MATLAB 该函数接受一个参数 并返回两个值 和 。
-
:这是函数体的一行代码,计算向量 的均值,并将结果存储在变量 。
-
:这是函数体的另一行代码,计算向量 的标准差,并将结果存储在变量 。
现在在命令窗口中用一些随机数测试它,例如:
讯享网
在这个示例中,我们将数据向量 作为参数传递给 函数,该函数将计算 的均值并将结果存储在变量 中,同时计算标准差并将结果存储在变量 中。
1. 函数的一般形式
函数m -文件名 的一般形式如下:
讯享网
2. 关键字function
函数文件必须以关键字function开头(在函数定义行中)。
3. 输入和输出参数
输入和输出参数(inputarg1, outputarg1等)是“虚拟”变量,仅用于定义函数与工作区的通信方式。因此,当调用(引用)函数时,可以使用其他变量名来代替它们。
4.多个输出参数
如果有多个输出参数,则必须在函数定义行中用逗号分隔输出参数并将其括在方括号中。
但是,当使用多个输出参数调用函数时,实际的输出参数可能用逗号或空格分隔。如果只有一个输出参数,则不需要方括号。
5. 函数命名规范
函数名必须遵循变量名的MATLAB规则。如果文件名和函数定义行名不同,则忽略内部名称。
6. 帮助文本
当您输入help function_name时,MATLAB将显示出现在函数定义行和第一个非注释(可执行或空白)行之间的注释行。
在MATLAB中,第一行注释被称为H1行,它提供了函数用途的简要描述。而lookfor函数专门搜索并显示H1行,用于在特定主题上查找帮助信息。
在Matlab中,可以为整个目录创建帮助文本,方法是在该目录中创建一个名为Contents.m的文件,并在该文件中添加注释行。该文件必须只包含注释行,不能包含任何可执行代码。
Contents.m文件的内容将在使用help命令时显示。例如,如果要查看名为mydir的目录的帮助文本,可以在Matlab命令窗口中输入help mydir,然后按下回车键。如果mydir目录中存在Contents.m文件,则该文件的内容将被显示出来。如果mydir目录中不存在Contents.m文件,则会显示每个M文件的H1行。
使用Contents.m文件可以为整个目录提供统一的帮助文本,方便用户了解该目录中包含的函数和脚本的作用和用法。同时,也可以在Contents.m文件中添加目录级别的说明和注释,帮助用户更好地理解该目录的内容和结构。
7. 局部变量:范围
在函数内部定义的任何变量都不能在函数外部访问。这样的变量被称为局部变量——它们只存在于函数中,函数有自己的工作空间,与命令窗口中定义的变量的基本工作空间是分开的。这意味着,如果在函数中使用变量作为循环索引,它将不会与工作空间或其他函数中的同名变量发生冲突。
局部变量的作用域仅限于定义它们的函数,因此它们不能被其他函数或脚本访问。局部变量的作用域是在定义它们的函数内部。当函数被调用时,Matlab会为该函数创建一个新的工作空间,该工作空间包含该函数的所有局部变量。当函数执行完毕后,该工作空间将被销毁,其中的局部变量也将被删除。
局部变量的作用域可以通过使用global关键字来扩展到整个Matlab会话。使用global关键字定义的变量可以在任何函数或脚本中使用,但是需要在每个函数或脚本中使用global关键字声明该变量。
局部变量的作用域还可以通过使用persistent关键字来扩展到函数调用之间。使用persistent关键字定义的变量在函数调用之间保持不变,但是只能在定义它们的函数中使用。
在编写Matlab代码时,应该尽可能使用局部变量,以避免命名冲突和不必要的内存使用。同时,应该避免在函数内部修改全局变量的值,以确保代码的可维护性和可重用性。
8. 全局变量
在基本工作空间中定义的变量通常不能在函数内部访问,也就是说,它们的作用域仅限于工作空间本身,除非它们被声明为全局的,例如:. 如果几个函数(可能还有基本工作空间)都将特定变量声明为全局变量,那么它们都共享这些变量的单个副本。MATLAB建议用大写字母键入全局变量,以提醒您它们是全局的
函数如果A是全局的返回1,否则返回0。命令给出了一个全局变量列表。使用将所有变量变为非全局变量,或者使用clear PLINK将PLINK变为非全局变量。
在Matlab中,可以使用clear命令将变量从工作空间中删除。如果PLINK是全局变量,可以使用以下命令将其变为非全局变量:
-
在任何函数或脚本中使用命令将PLINK从全局变量中删除。
-
在定义PLINK的函数或脚本中使用命令将其从局部变量中删除。
在执行这些命令之后,PLINK将不再是全局变量,而是一个普通的局部变量或未定义的变量。如果需要重新定义PLINK,可以在函数或脚本中重新声明它,或者在命令行中重新分配它的值。
9. 持久变量
函数中的变量可以声明为持久变量. 局部变量通常在函数返回时停止存在。然而,在函数调用之间,持久变量仍然存在。持久化变量初始化为空数组。
在Matlab中,persistent变量是在函数内部定义的变量,但是它们的作用域可以扩展到函数调用之间。与局部变量不同,persistent变量在函数调用之间保持不变,而不是在每次函数调用时重新创建。
使用persistent关键字定义的变量只能在定义它们的函数中使用,但是它们的值在函数调用之间保持不变。这使得persistent变量非常适合存储需要在函数调用之间保持不变的信息,例如计数器或状态信息。
在定义persistent变量时,必须在变量名前面加上persistent关键字。例如,以下代码定义了一个名为count的persistent变量:
在这个例子中,count变量被定义为persistent变量,并且在每次函数调用之间保持不变。如果count变量尚未被定义,它将被初始化为0。每次函数被调用时,count变量的值将增加1,并在命令窗口中显示。
需要注意的是,persistent变量的值在Matlab会话结束时不会被清除。如果需要清除persistent变量的值,可以使用clear命令,例如:
讯享网
这将清除myFunction函数中名为count的persistent变量的值。
m文件中的mlock函数可以防止m文件被清除。被锁的m文件可以用munlock解锁。mislocked函数表示m文件是否可以清除。
在Matlab中,mlock函数可以用来防止m文件被清除。当一个m文件被锁定时,它将不会被清除,直到它被解锁。这对于需要在多个函数之间共享数据的情况非常有用。
以下是一个示例,演示如何使用mlock和munlock函数:
在这个例子中,myFunction函数使用函数锁定了m文件,以便在函数调用之间保持myGlobalVar变量的值。另一个函数myOtherFunction使用函数解锁m文件,以便在需要时可以清除m文件。
另外,函数可以用来检查一个m文件是否被锁定。如果一个m文件被锁定,函数将返回,否则返回。以下是一个示例:
讯享网
在这个例子中,myFunction函数使用mlock函数锁定了m文件。checkLock函数使用mislocked函数检查myFunction是否被锁定,并在命令窗口中显示相应的消息。
10. 不返回值的函数
你可能希望编写一个不返回值的函数(在像Pascal和Fortran这样的语言中,这种函数被称为过程或子程序,在C++和Java中则称为空类型)。在这种情况下,只需省略函数定义行中的输出参数和等号。例如,下面的函数将显示n个星号:
11. 矢量参数
输入和输出参数可能是向量,例如,下面的函数生成一个随机掷n次骰子的向量:
讯享网
当输出参数是一个向量时,每次调用函数时都会初始化,任何之前的元素都会被清除。因此,它在任何时候的大小都由函数的最近调用决定。
例如,假设函数定义为
如果b在基本工作区中定义为, 语句 结果是
12. 函数参数是如何传递的
如果一个函数改变了它的任何一个输入参数的值,那么在返回到工作区时,这个改变不会反映在实际的输入参数中(除非用相同的输入和输出参数调用这个函数——见下文)。对于有技术头脑的人来说,输入参数似乎是按值传递的。
您可能认为按值传递一个大矩阵作为输入参数是对内存的浪费,您可能是对的。然而,MATLAB的设计者意识到了这一点,因此输入参数只有在函数修改时才按值传递(尽管修改不会在返回时反映出来)。如果函数不修改输入参数,则通过引用传递。
13. “模拟按引用传递”
在Matlab中,传递参数通常是按值传递的,这意味着函数接收到的参数是原始变量的副本,而不是原始变量本身。这种方式有时会导致问题,特别是当需要修改原始变量的值时。
为了解决这个问题,Matlab提供了一种称为“模拟按引用传递”的技术。这种技术使用句柄对象来传递参数,而不是直接传递变量的值。句柄对象是指向变量的指针,因此可以通过句柄对象修改原始变量的值。
以下示例演示如何使用模拟按引用传递技术:
讯享网
在这个例子中,我们定义了一个句柄类MyHandleClass,它有一个属性Value。我们还定义了一个函数myFunction,它使用句柄对象myHandle传递参数,并将myHandle的Value属性增加1。最后,我们创建一个句柄对象myHandle,并将其传递给myFunction函数。
通过使用句柄对象,我们可以修改原始变量的值,而不是只修改副本的值。这种技术在需要修改原始变量的值时非常有用,特别是在处理大型数据集时。
14. 检查函数参数的数量
函数可以带全部、部分或不带任何输入参数调用。如果不带参数调用,则必须省略括号。您不能使用比其定义中显示的更多的输入参数。
这同样适用于输出参数—在使用函数时可以指定全部、部分或不指定它们。如果调用没有输出参数的函数,则返回定义中第一个参数的值。有时,函数可能需要知道在特定调用中使用了多少输入/输出参数。在这种情况下,可以使用函数和来确定实际输入和输出参数的数量。
例如,
将显示每次调用时出现的输入参数的数量。
15. 传递可变数量的参数
函数varargin和varargout允许您调用具有任意数量的输入或输出参数的函数。由于这个工具涉及到将参数打包到单元格数组中,对它的讨论推迟到第11章。
一个函数文件可以包含多个函数的代码。文件中的第一个函数是主函数,是用m文件名调用的函数。文件中的其他函数称为子函数,仅对主函数和其他子函数可见。每个子函数都以自己的函数定义行开始。子函数以任意顺序跟在主函数之后。
在Matlab中,一个m文件可以包含多个函数,这些函数被称为子函数。子函数可以访问主函数中定义的变量和函数,但主函数不能访问子函数中定义的变量和函数。
以下是一个示例,演示如何使用子函数:
讯享网
在这个例子中,我们定义了一个主函数myMainFunction,它定义了一个变量myVar,并调用了一个子函数mySubFunction。子函数修改了myVar的值,但主函数仍然显示原始值1,因为子函数中修改的是子函数中定义的变量,而不是主函数中定义的变量。
使用子函数可以使代码更加模块化和易于维护。子函数可以将复杂的任务分解为更小的任务,并使代码更易于理解和调试。
私有函数是驻留在名为private的子目录中的函数。私有函数只对父目录中的函数可见。
在Matlab中,可以使用访问修饰符来控制函数的可见性。其中,private访问修饰符可以将函数设置为私有函数,只能在同一类中访问,而不能在其他类或脚本中访问。
以下是一个示例,演示如何使用私有函数:
在这个例子中,我们定义了一个类MyClass,它有一个属性myVar和两个方法myPublicFunction和myPrivateFunction。myPublicFunction是公共函数,可以在其他类或脚本中访问,它调用了私有函数myPrivateFunction。myPrivateFunction是私有函数,只能在同一类中访问,它显示myVar的值。
使用私有函数可以隐藏类的实现细节,防止其他类或脚本直接访问类的内部函数,从而提高代码的安全性和可维护性。私有函数还可以将类的实现细节封装起来,使类的接口更加简洁和易于使用。
在Matlab中,P-code文件是一种加密的二进制文件格式,可以用于保护Matlab代码的知识产权和加速代码的执行。P-code文件是通过将Matlab代码编译为二进制格式生成的,与Matlab源代码不同,P-code文件不能被直接编辑或查看。
以下是一个示例,演示如何生成P-code文件:
讯享网
在这个例子中,我们定义了一个函数myFunction,并使用pcode命令将其编译为P-code文件。生成的P-code文件可以在Matlab中使用,但不能被直接编辑或查看。
使用P-code文件可以保护Matlab代码的知识产权,防止其他人直接查看或修改代码。P-code文件还可以加速代码的执行,因为它们是预编译的二进制文件,不需要在运行时进行解释和编译。
在Matlab中,可以使用Profiler工具来分析和优化M文件的性能。Profiler可以帮助用户找出代码中的瓶颈和性能问题,并提供详细的性能分析报告和建议。
在这个例子中,我们定义了一个函数myFunction,它生成一个大矩阵并计算矩阵的逆和行列式。我们可以使用Profiler工具来分析这个函数的性能:
-
在Matlab命令窗口中输入,启动Profiler工具。
-
调用myFunction函数,执行代码。
-
在Matlab命令窗口中输入,打开Profiler工具的分析报告。
Profiler工具会生成一个详细的性能分析报告,包括函数的执行时间、函数调用次数、内存使用情况等信息。通过分析这些信息,我们可以找出代码中的瓶颈和性能问题,并进行优化。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/208633.html