# 1.6 高阶函数

``````>>> def square(x):
return x * x
``````

``````>>> 3 * 3
9
>>> 5 * 5
25
``````

## 1.6.1 作为参数的函数

``````>>> def sum_naturals(n):
total, k = 0, 1
while k <= n:
total, k = total + k, k + 1
>>> sum_naturals(100)
5050
``````

``````>>> def sum_cubes(n):
total, k = 0, 1
while k <= n:
total, k = total + pow(k, 3), k + 1
>>> sum_cubes(100)
25502500
``````

``````>>> def pi_sum(n):
total, k = 0, 1
while k <= n:
total, k = total + 8 / (k * (k + 2)), k + 4
>>> pi_sum(100)
3.121594652591009
``````

``````def <name>(n):
total, k = 0, 1
while k <= n:
total, k = total + <term>(k), <next>(k)
``````

``````>>> def summation(n, term, next):
total, k = 0, 1
while k <= n:
total, k = total + term(k), next(k)
``````

``````>>> def cube(k):
return pow(k, 3)
>>> def successor(k):
return k + 1
>>> def sum_cubes(n):
return summation(n, cube, successor)
>>> sum_cubes(3)
36
``````

``````>>> def identity(k):
return k
>>> def sum_naturals(n):
return summation(n, identity, successor)
>>> sum_naturals(10)
55
``````

``````>>> def pi_term(k):
denominator = k * (k + 2)
return 8 / denominator
>>> def pi_next(k):
return k + 4
>>> def pi_sum(n):
return summation(n, pi_term, pi_next)
>>> pi_sum(1e6)
3.1415906535898936
``````

## 1.6.2 作为一般方法的函数

``````>>> def iter_improve(update, test, guess=1):
while not test(guess):
guess = update(guess)
return guess
``````

`test`函数通常检查两个函数`f``g``guess`值上是否彼此接近。测试`f(x)`是否接近于`g(x)`也是计算的一般方法。

``````>>> def near(x, f, g):
return approx_eq(f(x), g(x))
``````

``````>>> def approx_eq(x, y, tolerance=1e-5):
return abs(x - y) < tolerance
``````

``````>>> def golden_update(guess):
return 1/guess + 1
>>> def golden_test(guess):
return near(guess, square, successor)
``````

``````>>> iter_improve(golden_update, golden_test)
1.6180371352785146
``````

``````>>> phi = 1/2 + pow(5, 1/2)/2
>>> def near_test():
assert near(phi, square, successor), 'phi * phi is not near phi + 1'
>>> def iter_improve_test():
approx_phi = iter_improve(golden_update, golden_test)
assert approx_eq(phi, approx_phi), 'phi differs from its approximation'
``````

## 1.6.3 定义函数 III：嵌套定义

``````>>> def average(x, y):
return (x + y)/2
>>> def sqrt_update(guess, x):
return average(guess, x/guess)
``````

``````>>> def square_root(x):
def update(guess):
return average(guess, x/guess)
def test(guess):
return approx_eq(square(guess), x)
return iter_improve(update, test)
``````

1. 每个用户定义的函数都有一个关联环境：它的定义所在的环境。
2. 当一个用户定义的函数调用时，它的局部帧扩展于函数所关联的环境。

``````>>> square_root(256)
16.00000000000039
``````

• 局部函数的名称并不影响定义所在函数外部的名称，因为局部函数的名称绑定到了定义处的当前局部环境中，而不是全局环境。
• 局部函数可以访问外层函数的环境。这是因为局部函数的函数体的求值环境扩展于定义处的求值环境。

`update`函数自带了一些数据：也就是在定义处环境中的数据。因为它以这种方式封装信息，局部定义的函数通常叫做闭包。

## 1.6.4 作为返回值的函数

``````>>> def compose1(f, g):
def h(x):
return f(g(x))
return h
169
``````

`compose1`中的`1`表明复合函数和返回值都只接受一个参数。这种命名惯例并不由解释器强制，`1`只是函数名称的一部分。

## 1.6.5 Lambda 表达式

Lambda 表达式十分受限：它们仅仅可用于简单的单行函数，求解和返回一个表达式。在它们适用的特殊情形中，Lambda 表达式具有强大的表现力。

``````>>> def compose1(f,g):
return lambda x: f(g(x))
``````

``````     lambda            x            :          f(g(x))
"A function that    takes x    and returns     f(g(x))"
``````

``````>>> compose1 = lambda f,g: lambda x: f(g(x))
``````

Lambda 的术语是一个历史的偶然结果，来源于手写的数学符号和早期打字系统限制的不兼容。

-- Peter Norvig (norvig.com/lispy2.html)

## 1.6.6 示例：牛顿法

• 16 的平方根是满足`square(x) - 16 = 0``x`值。
• 以 2 为底 32 的对数（例如 2 与某个指数的幂为 32）是满足`pow(2, x) - 32 = 0``x`值。

``````>>> def square_root(a):
return find_root(lambda x: square(x) - a)
>>> def logarithm(a, base=2):
return find_root(lambda x: pow(base, x) - a)
``````

• `f(x) = square(x) - 16`（细线）
• `f(x) = pow(2, x) - 32`（粗线）

``````>>> def approx_derivative(f, x, delta=1e-5):
df = f(x + delta) - f(x)
return df/delta
>>> def newton_update(f):
def update(x):
return x - f(x) / approx_derivative(f, x)
return update
``````

``````>>> def find_root(f, initial_guess=10):
def test(x):
return approx_eq(f(x), 0)
return iter_improve(newton_update(f), test, initial_guess)
>>> square_root(16)
4.000000000026422
>>> logarithm(32, 2)
5.000000094858201
``````

## 1.6.7 抽象和一等函数

1. 它们可以绑定到名称。
2. 它们可以作为参数向函数传递。
3. 它们可以作为函数的返回值返回。
4. 它们可以包含在好素具结构中。

Python 总是给予函数一等地位，所产生的表现力的收益是巨大的。另一方面，控制结构不能做到：你不能像使用`sum`那样将`if`传给一个函数。

## 1.6.8 函数装饰器

Python 提供了特殊的语法，将高阶函数用作执行`def`语句的一部分，叫做装饰器。

``````>>> def trace1(fn):
def wrapped(x):
print('-> ', fn, '(', x, ')')
return fn(x)
return wrapped
>>> @trace1
def triple(x):
return 3 * x
>>> triple(12)
->  <function triple at 0x102a39848> ( 12 )
36
``````

``````>>> def triple(x):
return 3 * x
>>> triple = trace1(triple)
``````