函数句柄 #

一、函数句柄概述 #

函数句柄是一种存储函数引用的变量,可以将函数作为参数传递:

matlab
% 创建函数句柄
f = @sin;      % 内置函数
g = @my_func;  % 自定义函数

% 使用句柄调用函数
f(pi/2)        % 1

二、创建函数句柄 #

2.1 命名函数句柄 #

matlab
% 内置函数
f = @sin;
f(pi/2)  % 1

% 自定义函数
% 保存为 square.m
function result = square(x)
    result = x^2;
end

% 创建句柄
g = @square;
g(5)  % 25

2.2 匿名函数句柄 #

matlab
% 匿名函数本身就是句柄
f = @(x) x^2 + 2*x + 1;
f(3)  % 16

% 多参数
g = @(x, y) x*y + x + y;
g(2, 3)  % 11

2.3 方法句柄 #

matlab
% 类方法句柄
obj = MyClass();
method_handle = @obj.myMethod;

% 调用
method_handle(args);

三、函数句柄属性 #

3.1 查看句柄信息 #

matlab
f = @sin;

% 查看函数名
func2str(f)  % 'sin'

% 查看函数信息
functions(f)
% function: 'sin'
% type: 'simple'
% file: ''

% 检查是否为句柄
isa(f, 'function_handle')  % true

3.2 句柄比较 #

matlab
f1 = @sin;
f2 = @sin;
f3 = @cos;

% 使用isequal比较
isequal(f1, f2)  % true
isequal(f1, f3)  % false

% 使用eq比较
f1 == f2  % true

四、函数句柄作为参数 #

4.1 传递给函数 #

matlab
% 接受函数句柄作为参数
function result = apply_function(f, x)
    result = f(x);
end

% 使用
apply_function(@sin, pi/2)  % 1
apply_function(@(x) x^2, 5)  % 25

4.2 数值积分 #

matlab
% 定义被积函数
f = @(x) exp(-x.^2);

% 计算积分
result = integral(f, 0, Inf);
fprintf('积分结果: %.6f\n', result);  % 0.886227

4.3 方程求解 #

matlab
% 定义方程
f = @(x) x^2 - 4;

% 求根
roots = fzero(f, 1);  % 从1开始搜索
fprintf('根: %.4f\n', roots);  % 2.0000

4.4 优化问题 #

matlab
% 定义目标函数
f = @(x) (x(1)-1)^2 + (x(2)-2)^2;

% 最小化
x0 = [0, 0];
[x_opt, f_opt] = fminsearch(f, x0);
fprintf('最优点: (%.4f, %.4f), 最小值: %.4f\n', x_opt(1), x_opt(2), f_opt);
% 最优点: (1.0000, 2.0000), 最小值: 0.0000

五、函数句柄数组 #

5.1 创建句柄数组 #

matlab
% 函数句柄数组
funcs = {@sin, @cos, @tan, @exp};

% 使用
for i = 1:length(funcs)
    fprintf('%.4f\n', funcs{i}(pi/4));
end
% 0.7071
% 0.7071
% 1.0000
% 2.1933

5.2 选择性执行 #

matlab
% 根据条件选择函数
operations = struct();
operations.add = @(a, b) a + b;
operations.subtract = @(a, b) a - b;
operations.multiply = @(a, b) a * b;
operations.divide = @(a, b) a / b;

% 使用
op = 'multiply';
result = operations.(op)(10, 5);
fprintf('%s: %d\n', op, result);  % multiply: 50

六、回调函数 #

6.1 定时器回调 #

matlab
% 创建定时器
t = timer;
t.TimerFcn = @(~,~) disp('定时器触发');
t.StartDelay = 2;  % 2秒后触发

start(t);
pause(3);
delete(t);

6.2 图形回调 #

matlab
% 按钮回调
fig = figure;
btn = uicontrol('Style', 'pushbutton', ...
                'String', '点击我', ...
                'Position', [100 100 100 30], ...
                'Callback', @(~,~) disp('按钮被点击'));

% 关闭图形
delete(fig);

6.3 事件处理 #

matlab
% 定义事件处理函数
function setup_event_handler()
    fig = figure;
    
    % 鼠标移动回调
    set(fig, 'WindowButtonMotionFcn', @mouse_moved);
    
    function mouse_moved(~, ~)
        pos = get(fig, 'CurrentPoint');
        title(sprintf('位置: (%.0f, %.0f)', pos(1), pos(2)));
    end
end

七、参数化函数句柄 #

7.1 捕获参数 #

matlab
% 创建参数化函数
function f = make_quadratic(a, b, c)
    f = @(x) a*x^2 + b*x + c;
end

% 使用
f1 = make_quadratic(1, 0, -1);  % x^2 - 1
f2 = make_quadratic(2, 3, 1);   % 2x^2 + 3x + 1

f1(2)  % 3
f2(1)  % 6

7.2 工厂函数 #

matlab
% 函数工厂
function processor = make_processor(method)
    switch method
        case 'normalize'
            processor = @(data) (data - min(data)) / (max(data) - min(data));
        case 'standardize'
            processor = @(data) (data - mean(data)) / std(data);
        case 'log'
            processor = @(data) log(data + 1);
        otherwise
            error('未知方法');
    end
end

% 使用
norm_func = make_processor('normalize');
data = [1 2 3 4 5];
normalized = norm_func(data);

八、实用示例 #

8.1 数值微分 #

matlab
function df = numerical_derivative(f, x)
% NUMERICAL_DERIVATIVE 数值微分
    h = 1e-8;
    df = (f(x + h) - f(x - h)) / (2 * h);
end

% 使用
f = @sin;
df = numerical_derivative(f, pi/4);
fprintf('sin在pi/4处的导数: %.6f (理论值: %.6f)\n', df, cos(pi/4));

8.2 数值积分 #

matlab
function I = simpson_integral(f, a, b, n)
% SIMPSON_INTEGRAL 辛普森积分法
    h = (b - a) / n;
    x = linspace(a, b, n + 1);
    y = f(x);
    
    I = h/3 * (y(1) + y(end) + 4*sum(y(2:2:end-1)) + 2*sum(y(3:2:end-2)));
end

% 使用
f = @(x) sin(x);
I = simpson_integral(f, 0, pi, 100);
fprintf('积分结果: %.6f (理论值: 2.000000)\n', I);

8.3 自定义映射函数 #

matlab
function result = my_map(func, data)
% MY_MAP 对数据应用函数
    if iscell(data)
        result = cellfun(func, data, 'UniformOutput', false);
    else
        result = arrayfun(func, data);
    end
end

% 使用
data = [1 2 3 4 5];
squares = my_map(@(x) x^2, data);
% [1 4 9 16 25]

names = {'apple', 'banana'};
upper_names = my_map(@upper, names);
% {'APPLE', 'BANANA'}

九、最佳实践 #

9.1 选择合适的句柄类型 #

matlab
% 简单函数:匿名函数
f = @(x) x^2;

% 复杂函数:命名函数
% 保存为 complex_calculation.m
function result = complex_calculation(x)
    % 复杂计算
end

% 使用句柄
f = @complex_calculation;

9.2 文档化函数句柄 #

matlab
% 为参数化函数添加文档
function f = make_gaussian(mu, sigma)
% MAKE_GAUSSIAN 创建高斯函数句柄
%   f = make_gaussian(mu, sigma) 返回高斯函数句柄
%
%   输入:
%       mu    - 均值
%       sigma - 标准差
%
%   输出:
%       f - 函数句柄 @(x) 高斯函数值
%
%   示例:
%       f = make_gaussian(0, 1);
%       y = f(0);  % 0.3989

    f = @(x) 1/(sigma*sqrt(2*pi)) * exp(-(x-mu).^2/(2*sigma^2));
end

9.3 错误处理 #

matlab
function result = safe_apply(f, x)
% SAFE_APPLY 安全应用函数
    
    if ~isa(f, 'function_handle')
        error('第一个参数必须是函数句柄');
    end
    
    try
        result = f(x);
    catch ME
        warning('函数执行失败: %s', ME.message);
        result = NaN;
    end
end

十、总结 #

本章学习了:

  1. 创建句柄:命名函数、匿名函数
  2. 句柄属性:func2str、functions
  3. 作为参数:传递给其他函数
  4. 句柄数组:存储多个函数
  5. 回调函数:定时器、图形回调
  6. 参数化句柄:捕获外部变量
  7. 实用示例:数值微分、积分

下一章将学习递归函数。

最后更新:2026-03-27