匿名函数是MATLAB语言的强大工具。它们是本地存在的功能,即:在当前工作空间中。但是,它们不像常规函数那样存在于MATLAB路径中,例如在m文件中。这就是为什么它们被称为匿名的原因,尽管它们在工作空间中可以具有类似变量的名称。
使用@运算符创建匿名函数和函数句柄。例如,创建sin函数(正弦)的句柄并将其用作f:
>> f = @sin f = @sin
现在f是该sin函数的句柄。就像(在现实生活中)门把手是使用门的一种方式一样,功能把手是使用功能的一种方式。要使用f,参数将传递给它,就像它是sin函数一样:
>> f(pi/2) ans = 1
f接受sin函数接受的任何输入参数。如果sin将是一个接受零个输入参数的函数(它不接受,但其他人接受,例如该peaks函数),f()则将在没有输入参数的情况下调用它。
像sin上面的示例一样,创建现有函数的句柄显然没有用。在该示例中,这是多余的。但是,创建匿名函数来执行自定义操作很有用,否则这些匿名函数将需要重复多次或为其创建单独的函数。作为一个接受一个变量作为输入的自定义匿名函数的示例,将信号的正弦和余弦平方求和:
>> f = @(x) sin(x)+cos(x).^2 f = @(x)sin(x)+cos(x).^2
现在f接受一个称为的输入参数x。这是(...)在@运算符后直接使用括号指定的。f现在是一个匿名函数x:f(x)。通过将值传递x给使用f:
>> f(pi) ans = 1.0000
值的向量或变量也可以传递给f,只要它们在以下范围内以有效方式使用f:
>> f(1:3) % pass a vector to f ans = 1.1334 1.0825 1.1212 >> n = 5:7; >> f(n) % pass n to f ans = -0.8785 0.6425 1.2254
以相同的方式,可以创建匿名函数来接受多个变量。接受三个变量的匿名函数的示例:
>> f = @(x,y,z) x.^2 + y.^2 - z.^2 f = @(x,y,z)x.^2+y.^2-z.^2 >> f(2,3,4) ans = -3
工作空间中的变量可以在匿名函数的定义中使用。这称为参数化。例如,要c = 2在匿名函数中使用常量:
>> c = 2; >> f = @(x) c*x f = @(x)c*x >> f(3) ans = 6
f(3)使用变量c作为参数与提供的相乘x。请注意,如果此时将的值c设置为其他值,则将f(3)其调用,结果将不会有所不同。的值c是创建匿名函数时的值:
>> c = 2; >> f = @(x) c*x; >> f(3) ans = 6 >> c = 3; >> f(3) ans = 6
请注意,将工作空间中的变量名称用作匿名函数的输入参数之一(即,使用@(...))将不会使用这些变量的值。相反,它们在匿名函数的范围内被视为不同的变量,即:匿名函数具有其专用工作区,其中输入变量从不引用主工作区中的变量。主工作区和匿名函数的工作区不了解彼此的内容。一个例子来说明这一点:
>> x = 3 % x in main workspace x = 3 >> f = @(x) x+1; % here x refers to a private x variable >> f(5) ans = 6 >> x x = 3
的值x从主工作空间没有内使用f。此外,在主工作区x中保持不变。在的范围内f,@运算符后括号之间的变量名称独立于主要工作空间变量。
匿名函数(或更准确地说,指向匿名函数的函数句柄)与任何其他值一样存储在当前工作空间中:存储在变量(如上所示),单元格数组({@(x)x.^2,@(x)x+1})或甚至属性(如h.ButtonDownFcn交互式图形)。这意味着匿名函数可以像其他任何值一样对待。将其存储在变量中时,它在当前工作空间中具有名称,可以像保存数字的变量一样进行更改和清除。
换句话说:函数句柄(无论是@sin形式还是匿名函数)只是一个可以存储在变量中的值,就像数值矩阵一样。
由于函数句柄被视为变量,因此可以将它们传递给接受函数句柄作为输入参数的函数。
一个示例:在m文件中创建一个接受函数句柄和标量数字的函数。然后,通过传递3给函数句柄来调用它,然后将标量数字添加到结果中。返回结果。
内容funHandleDemo.m:
function y = funHandleDemo(fun,x) y = fun(3); y = y + x;
将其保存在路径中的某个位置,例如在MATLAB的当前文件夹中。现在funHandleDemo可以如下使用,例如:
>> f = @(x) x^2; % an anonymous function >> y = funHandleDemo(f,10) % pass f and a scalar to funHandleDemo y = 19
另一个现有函数的句柄可以传递给funHandleDemo:
>> y = funHandleDemo(@sin,-5) y = -4.8589
请注意,如何@sin快速访问sin函数而无需先使用将该函数存储在变量中f = @sin。
MATLAB具有一些内置函数,这些函数接受匿名函数作为输入。这是用最少的代码行执行许多计算的方法。例如bsxfun,它执行逐个元素的二进制运算,即:它以逐个元素的方式在两个向量或矩阵上应用函数。通常,这将需要使用for-loop,这通常需要预先分配速度。bsxfun加快使用此过程。下面的示例使用tic和演示了此toc功能,这两个函数可用于计时代码花费的时间。它根据矩阵列的平均值计算每个矩阵元素的差。
A = rand(50); % 50-by-50 matrix of random values between 0 and 1 % method 1: slow and lots of lines of code tic meanA = mean(A); % mean of every matrix column: a row vector % pre-allocate result for speed, remove this for even worse performance result = zeros(size(A)); for j = 1:size(A,1) result(j,:) = A(j,:) - meanA; end toc clear result % make sure method 2 creates its own result % method 2: fast and only one line of code tic result = bsxfun(@minus,A,mean(A)); toc
运行上面的示例将产生两个输出:
Elapsed time is 0.015153 seconds. Elapsed time is 0.007884 seconds.
这些行来自toc函数,这些函数打印自上次调用tic函数以来经过的时间。
该bsxfun调用将第一个输入参数中的函数应用于其他两个输入参数。@minus是与减号相同的操作的长名称。@只要已接受A并mean(A)用作生成有意义结果的输入,就可以指定与其他任何函数不同的匿名函数或句柄()。
特别是对于大型矩阵中的大量数据,bsxfun可以大大加快处理速度。它也使代码看起来更简洁,尽管对于不了解MATLAB或的人来说可能很难解释bsxfun。(请注意,在MATLAB R2016a及更高版本中,许多以前使用的操作bsxfun不再需要它们;它们可以直接运行,在某些情况下甚至可以更快地运行。)A-mean(A)