什么是函数句柄以及它如何有用?

Dik*_*kla 38 matlab function function-handle

有人可以向我解释@(函数句柄)运算符的含义以及使用它的原因吗?

gno*_*ice 49

MATLAB中的函数句柄操作符基本上类似于指向函数的特定实例的指针.其他一些答案已经讨论了它的一些用途,但我将在这里添加另一个用途,我经常使用它:维护对不再"在范围内"的函数的访问.

例如,以下函数初始化一个值count,然后将函数句柄返回到嵌套函数increment:

function fHandle = start_counting(count)

  disp(count);
  fHandle = @increment;

  function increment
    count = count+1;
    disp(count);
  end

end
Run Code Online (Sandbox Code Playgroud)

由于函数increment嵌套函数,因此它只能在函数内使用start_counting(即工作空间start_counting是"范围").但是,通过返回函数的句柄increment,我仍然可以在它之外使用它start_counting,它仍然保留对工作区中变量的访问权限start_counting!这允许我这样做:

>> fh = start_counting(3);  % Initialize count to 3 and return handle
     3

>> fh();  % Invoke increment function using its handle
     4

>> fh();
     5
Run Code Online (Sandbox Code Playgroud)

请注意,即使我们在函数之外,我们也可以继续递增计数start_counting.但是你可以通过start_counting使用不同的数字再次调用并将函数句柄存储在另一个变量中来做更有趣的事情:

>> fh2 = start_counting(-4);
    -4

>> fh2();
    -3

>> fh2();
    -2

>> fh();  % Invoke the first handle to increment
     6

>> fh2();  % Invoke the second handle to increment
    -1
Run Code Online (Sandbox Code Playgroud)

请注意,这两个不同的计数器独立运行.该函数处理fhfh2指向函数的不同实例,其中increment包含用于包含唯一值的不同工作空间count.

除了上述内容之外,将函数句柄与嵌套函数结合使用还可以帮助简化GUI设计,正如我在其他SO帖子中所说明的那样.

  • 需要注意的一件事是,使用function关键字创建的函数和@运算符创建的函数具有不同的作用域规则.hGetCount = @ getCount; function c = getCount; C =计数; 结束; 如上所述,在评估时查找计数变量(使用词法作用域).函数hGetCount = @()count; 将在创建时替换count变量的值. (2认同)
  • 函数句柄允许您从主函数外部使用嵌套函数或子函数.它们可以帮助您进行GUI编程. (2认同)

小智 18

函数句柄是matlab中非常强大的工具.一个好的开始是阅读在线帮助,这将为您提供远远超出我的能力.在命令提示符下,键入

doc function_handle
Run Code Online (Sandbox Code Playgroud)

函数句柄是在一行中创建函数的简单方法.例如,假设我希望数值积分函数sin(k*x),其中k具有一些固定的外部值.我可以使用内联函数,但函数句柄更整洁.定义一个函数

k = 2;
fofx = @(x) sin(x*k);
Run Code Online (Sandbox Code Playgroud)

看到我现在可以在命令行中评估函数fofx.MATLAB知道k是什么,所以我们现在可以使用fofx作为函数.

fofx(0.3)
ans =
         0.564642473395035
Run Code Online (Sandbox Code Playgroud)

实际上,我们可以将fofx作为变量有效地传递.例如,让我们调用quad来进行数值积分.我会选择间隔[0,pi/2].

quad(fofx,0,pi/2)
ans =
         0.999999998199215
Run Code Online (Sandbox Code Playgroud)

如您所见,quad进行了数值积分.(顺便说一下,内联函数至少会有一个较慢的顺序,而且不太容易使用.)

x = linspace(0,pi,1000);
tic,y = fofx(x);toc
Elapsed time is 0.000493 seconds.
Run Code Online (Sandbox Code Playgroud)

通过比较,尝试内联函数.

finline = inline('sin(x*k)','x','k');
tic,y = finline(x,2);toc
Elapsed time is 0.002546 seconds.
Run Code Online (Sandbox Code Playgroud)

关于函数句柄的一个巧妙之处是你可以动态定义它.在[0,2*pi]区间内最小化函数cos(x)?

xmin = fminbnd(@(x) cos(x),0,2*pi)
xmin =
          3.14159265358979
Run Code Online (Sandbox Code Playgroud)

MATLAB中的函数句柄有许多其他用途.我只是在这里划了一眼.


Dan*_*ton 15

免责声明:未经测试的代码......

函数句柄操作符允许您创建对函数的引用并像其他任何变量一样传递它:

% function to add two numbers
function total = add(first, second) 
    total = first + second;
end

% this variable now points to the add function
operation = @add;
Run Code Online (Sandbox Code Playgroud)

一旦有了函数句柄,就可以像常规函数一样调用它:

operation(10, 20); % returns 30
Run Code Online (Sandbox Code Playgroud)

关于函数句柄的一个好处是你可以像其他任何数据一样传递它们,这样你就可以编写对其他函数起作用的函数.这通常可以让您轻松地分离出业务逻辑:

% prints hello
function sayHello 
    disp('hello world!');
end

% does something five times
function doFiveTimes(thingToDo) 
    for idx = 1 : 5 
        thingToDo();
    end
end

% now I can say hello five times easily:
doFiveTimes(@sayHello);

% if there's something else I want to do five times, I don't have to write
% the five times logic again, only the operation itself:
function sayCheese 
    disp('Cheese');
end
doFiveTimes(@sayCheese);

% I don't even need to explicitly declare a function - this is an 
% anonymous function:
doFiveTimes(@() disp('do something else'));
Run Code Online (Sandbox Code Playgroud)

Matlab的文档具有Matlab的语法的更详细的描述,并介绍了一些其他用途的函数处理如图形回调.