例如,假设您在m文件 A.m 中有一个主函数 A ,以及本地函数 D , E 和 F . 现在假设您分别在m文件 B.m 和 C.m 中有另外两个相关函数 B 和 C ,您还希望能够调用 D , E 和 F . 以下是您的一些选择:
将 D , E 和 F 分别放在各自的m文件中,允许任何其他函数调用它们 . 缺点是这些函数的范围很大,并不仅限于 A , B 和 C ,但好处是这很简单 .
使用 D , E 和 F 作为本地函数创建一个 defineMyFunctions m文件(类似于Jonas的示例),并且只是返回函数句柄的主函数 . 这允许您将 D , E 和 F 保留在同一个文件中,但它不会对这些函数的范围做任何事情,因为任何可以调用 defineMyFunctions 的函数都可以调用它们 . 然后,您还必须担心将函数句柄作为参数传递,以确保将它们放在您需要它们的位置 .
将 D , E 和 F 复制为 B.m 和 C.m 作为本地函数 . 这将其使用范围限制为 A , B 和 C ,但是由于您在不同位置拥有相同代码的三个副本,因此更新和维护代码是一场噩梦 .
Use private functions! 如果在同一目录中有 A , B 和 C ,则可以创建一个名为 private 的子目录,并在其中放置 D , E 和 F ,每个子目录作为单独的m文件 . 这限制了它们的范围,因此只能通过上面目录中的函数(即 A , B 和 C )调用它们,并将它们保存在同一个地方(但仍然是不同的m文件):
我非常喜欢SCFrench的答案 - 我想指出可以很容易地修改它以使用assignin函数将函数 directly 导入工作区 . (这样做让我想起了很多Python的"import x from y"做事方式)
function message = makefuns
assignin('base','fun1',@fun1);
assignin('base','fun2',@fun2);
message='Done importing functions to workspace';
end
function y=fun1(x)
y=x;
end
function z=fun2
z=1;
end
然后用于:
>> makefuns
ans =
Done importing functions to workspace
>> fun1(123)
ans =
123
>> fun2()
ans =
1
3
与SCFrench的答案一样,但更多的C#风格旋转..
我会(并且经常会)创建一个包含多个静态方法的类 . 例如:
classdef Statistics
methods(Static)
function val = MyMean(data)
val = mean(data);
end
function val = MyStd(data)
val = std(data);
end
end
end
由于方法是静态的,因此您无需实例化该类 . 您可以按如下方式调用函数:
data = 1:10;
mean = Statistics.MyMean(data);
std = Statistics.MyStd(data);
octave:8> help source
'source' is a built-in function
-- Built-in Function: source (FILE)
Parse and execute the contents of FILE. This is equivalent to
executing commands from a script file, but without requiring the
file to be named `FILE.m'.
255
您还可以将函数与main函数一起分组到一个主文件中,如下所示:
function [varargout] = main( subfun, varargin )
[varargout{1:nargout}] = feval( subfun, varargin{:} );
% paste your subfunctions below ....
function str=subfun1
str='hello'
function message = makefuns
assignin('base','fun1', @fun1); % Ru Hasha
assignin('base', 'fun2', @fun2); % Ru Hasha
message.fun1=@fun1; % SCFrench
message.fun2=@fun2; % SCFrench
end
function y=fun1(x)
y=x;
end
function z=fun2
z=1;
end
9 回答
通常,您的问题的答案是否定的,您不能为每个文件定义多个外部可见功能 . 但是,您可以将函数句柄返回到本地函数,一种方便的方法是将它们作为结构的字段 . 这是一个例子:
以下是它的使用方法:
在单个文件中具有多个可单独访问的函数的唯一方法是使用object-oriented programming定义STATIC METHODS . 您将访问该函数
myClass.static1()
,myClass.static2()
等 .OOP功能仅在R2008a之后才得到官方支持,因此除非你想使用旧的,未记录的OOP语法,否则你的答案是否定的,正如@gnovice所解释的那样 . .
EDIT
在文件中定义可从外部访问的多个函数的另一种方法是创建一个返回多个function handles的函数 . 换句话说,你将你的定义函数称为
[fun1,fun2,fun3]=defineMyFunctions
,之后你可以使用out1=fun1(inputs)
等 .调用该m文件时,将调用m文件中的第一个函数(即main function) . 主函数不需要与m文件具有相同的名称,但为了清楚起见,它应该是 . 当函数和文件名不同时,必须使用文件名来调用main函数 .
m文件中的所有后续函数(称为local functions(或旧术语中的"subfunctions"))只能由该m文件中的main函数和其他本地函数调用 . 其他m文件中的函数无法调用它们 . 从R2016b开始,您也可以add local functions to scripts,尽管范围行为仍然相同(即它们只能在脚本中调用) .
此外,您还可以在其他函数中声明函数 . 这些被称为nested functions,它们只能在它们嵌套的函数中调用 . 他们也可以访问嵌套它们的函数中的变量,这使得它们非常有用,尽管使用起来有些棘手 .
More food for thought...
有一些方法围绕上面概述的正常函数作用域行为,例如将function handles作为输出参数传递,如SCFrench和Jonas(从R2013b开始,由localfunctions函数促成)的答案中所述 . 但是,我不建议习惯于采用这种技巧,因为组织你的功能和文件可能有更好的选择 .
例如,假设您在m文件
A.m
中有一个主函数A
,以及本地函数D
,E
和F
. 现在假设您分别在m文件B.m
和C.m
中有另外两个相关函数B
和C
,您还希望能够调用D
,E
和F
. 以下是您的一些选择:将
D
,E
和F
分别放在各自的m文件中,允许任何其他函数调用它们 . 缺点是这些函数的范围很大,并不仅限于A
,B
和C
,但好处是这很简单 .使用
D
,E
和F
作为本地函数创建一个defineMyFunctions
m文件(类似于Jonas的示例),并且只是返回函数句柄的主函数 . 这允许您将D
,E
和F
保留在同一个文件中,但它不会对这些函数的范围做任何事情,因为任何可以调用defineMyFunctions
的函数都可以调用它们 . 然后,您还必须担心将函数句柄作为参数传递,以确保将它们放在您需要它们的位置 .将
D
,E
和F
复制为B.m
和C.m
作为本地函数 . 这将其使用范围限制为A
,B
和C
,但是由于您在不同位置拥有相同代码的三个副本,因此更新和维护代码是一场噩梦 .Use private functions! 如果在同一目录中有
A
,B
和C
,则可以创建一个名为private
的子目录,并在其中放置D
,E
和F
,每个子目录作为单独的m文件 . 这限制了它们的范围,因此只能通过上面目录中的函数(即A
,B
和C
)调用它们,并将它们保存在同一个地方(但仍然是不同的m文件):所有这些都超出了你的问题的范围,并且可能比你需要的更详细,但我认为可能很好地触及组织所有m文件的更普遍的关注 . ;)
我非常喜欢SCFrench的答案 - 我想指出可以很容易地修改它以使用assignin函数将函数 directly 导入工作区 . (这样做让我想起了很多Python的"import x from y"做事方式)
然后用于:
与SCFrench的答案一样,但更多的C#风格旋转..
我会(并且经常会)创建一个包含多个静态方法的类 . 例如:
由于方法是静态的,因此您无需实例化该类 . 您可以按如下方式调用函数:
我使用Octave在一个.m文件中定义多个函数,然后使用.m文件中的命令,我需要使用该文件中的函数:
不确定这是否适用于Matlab .
您还可以将函数与main函数一起分组到一个主文件中,如下所示:
然后调用 subfun1 将如下所示:str = main('subfun1')
截至R2017b,这不是正式可行的 . relevant documentation指出:
但是,在其他答案中建议的变通方法可以实现类似的功能 .
我尝试使用SCFRench并在_tatave上使用Ru Hasha .
And finally it works: 但我做了一些修改
可以在其他'm'文件中调用:
update:
我添加了一个答案,因为 neither 对于我来说是72和20 -749237_的八度音阶 . 我写的那个作品很完美(上周五我在后来写这篇文章时对它进行了测试) .