Fork me on GitHub

使用函数构建抽象

Chapter1: 使用函数构建抽象

高阶函数

作为一般方法的函数

  • sum_naturals()

    1
    2
    3
    4
    5
    6
    7
    >>> def sum_naturals(n):
    total, k = 0, 1
    while k <= n:
    total, k = total + k, k + 1
    return total
    >>> sum_naturals(100)
    5050
  • sum_cube()

    1
    2
    3
    4
    5
    6
    7
    >>> def sum_cubes(n):
    total, k = 0, 1
    while k <= n:
    total, k = total + pow(k, 3), k + 1
    return total
    >>> sum_cubes(100)
    25502500
  • sum_pi()

1
2
3
4
5
6
7
>>> def pi_sum(n):
total, k = 0, 1
while k <= n:
total, k = total + 8 / (k * (k + 2)), k + 4
return total
>>> pi_sum(100)
3.121594652591009

这三个函数在背后都具有相同模式。它们大部分相同,只是名字、用于计算被加项的k的函数,以及提供k的下一个值的函数不同。我们可以通过向相同的模板中填充槽位来生成每个函数:

1
2
3
4
5
def <name>(n):
total, k = 0, 1
while k <= n:
total, k = total + <term>(k), <next>(k)
return total

对于以上三个函数我们可以抽象成以下函数:

1
2
3
4
5
>>> def summation(n, term, next):
total, k = 0, 1
while k <= n:
total, k = total + term(k), next(k)
return total

要注意summation接受上界n,以及函数term和next作为参数。我们可以像任何函数那样使用summation,它简洁地表达了求和。

  • sum_cube()

    1
    2
    3
    4
    5
    6
    7
    8
    >>> 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
  • sum_pi()

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    def pi_term(k):
    return 8 / (k * (k + 2))

    def pi_next(k):
    return k+4

    def sum_pi(n):
    return summation(n, pi, next)

    >>> pi_sum(1e6)
    3.1415906535898936
  • 计算黄金分割比(gold ratio)

    1
    2
    3
    4
    5
    6
    >>> 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

$Lambda$ 表达式

Python 中,我们可以使用 Lambda 表达式凭空创建函数,它会求值为匿名函数。Lambda 表达式是函数体具有单个返回表达式的函数,不允许出现赋值和控制语句。

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

1
2
3
4
5
6
1	def compose1(f, g):
2 return lambda x: f(g(x))
3
4 f = compose1(lambda x: x * x,
5 lambda y: y + 1)
6 result = f(12)

抽象和一等函数

作为程序员,我们应该留意识别程序中低级抽象的机会,在它们之上构建,并泛化它们来创建更加强大的抽象。这并不是说,一个人应该总是尽可能以最抽象的方式来编程;专家级程序员知道如何选择合适于他们任务的抽象级别。但是能够基于这些抽象来思考,以便我们在新的上下文中能使用它们十分重要。高阶函数的重要性是,它允许我们更加明显地将这些抽象表达为编程语言中的元素,使它们能够处理其它的计算元素。

通常,编程语言会限制操作计算元素的途径。带有最少限制的元素被称为具有一等地位。一些一等元素的“权利和特权”是:

  • 它们可以绑定到名称。
  • 它们可以作为参数向函数传递。
  • 它们可以作为函数的返回值返回。
  • 它们可以包含在数据结构中。
  • Python 总是给予函数一等地位,所产生的表现力的收益是巨大的。另一方面,控制结构不能做到:你不能像使用sum那样将if传给一个函数。

补充阅读

如何正确理解Python函数是第一类对象

支持一下^-^
0%