用高阶函数做抽象

以函数作为参数,或者以函数作为返回值,这类能操作函数的函数称为高阶函数
  • 过程作为参数
    普通的求和:
def sum_naturals(n):
        total, k = 0, 1
        while k <= n:
            total, k = total + k, k + 1
        return total

对立方进行求和:

def sum_cubes(n):
        total, k = 0, 1
        while k <= n:
            total, k = total + k*k*k, k + 1
        return total

求和下列式子: 813+857+8911+...

def pi_sum(n):
        total, k = 0, 1
        while k <= n:
            total, k = total + 8 / ((4*k-3) * (4*k-1)), k + 1
        return total

三个过程共享着一种公共模式:

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

定义求和过程

#求和过程
def sum_term(n,term)#term是一个过程
    total,k=0,1
    while k <= n:
        total,k = total + term(k),k+1
    return total

#整数求和
def term_k(k):
    return k

#K^3求和
def term_k3(k):
    return k*k*k

#式子求和
def term_pi(k)
    return 8/((4*k-3)*(4*k-1))

def sum_pi(k)
    return sum_term(k,term_pi)

#调用过程
>>>sum_term(5,term_k)
>>>15

  • 过程作为一般性方法
def square_root_update(x,a):
    return (x+ a/x)/2


def cube_root_update(x,a):
    return ((2*x)+a/(x*x))/3

def improve(updata,close,guess=1):
    while not close(guess):
        guess = updata(guess)
    return guess
def approx_eq(x,y,tolerance=0.00001):
    return abs(x-y) < tolerance
#求平方根
def square_root(a):
    def updata(x):
        return square_root_update(x,a)
    def close(x):
        return approx_eq(x*x,a)
    return improve(updata,close)
#求3次根
def cube_root(a):
    def updata(x):
        return cube_root_update(x,a)
    def close(x):
        return approx_eq(x*x*x,a)
    return improve(updata,close)

找到函数的不动点 f(x)=x,xf(x) ,对于某些函数反复的应用

f(x),f(f(x))f(f(f(x))),....

直到值变化不大时,就可以找到它们的不动点

from math import *
def fixed_point(f,f_guess):
    def close_enough(x,y,tolerance=0.0001):
        return abs(x-y)< tolerance

    def try_guess(guess):
        next = f(guess)
        if close_enough(guess,next):
            return next
        else:
            return try_guess(next)
    return try_guess(f_guess)

注意return

可以将求平方根看成是一个不动点的问题,求 y2=xy=x/y ,定义sqrt函数:
(使用 f(x)=x/y 会造成结果不收敛,不让猜测变化太剧烈,答案在y和x/y之间,将猜测值设置为 f(x)=y+x/y2 ,该公式只是 y2=x 的变形)

def sqrt(x):
    return fixed_point(lambda y:(y+x/y)/2,1.0)

将函数作为参数传递,能够增强程序设计语言的表达能力。对公共模式进行了抽象。


  • 将函数作为返回值
    平均阻尼:给定一个函数f,考虑另一个函数,它在x处的值等于x和f(x)的平均值
#平均阻尼,传入某个函数,返回x和f(x)的平均值
def damp(f):
    return lambda x:(x+f(x))/2
#改写sqrt,利用damp函数获取(y+x/y)/2
def sqrt(x):
    return fixed_point(damp(lambda y:x/y),1.0)

#立方根不动点的函数是$y=x/y^2$,定义立方根函数为:
def sqrt(x):
    return fixed_point(damp(lambad y :x/(y*y)),1.0)

牛顿法
导数的定义:

Dg(x)=g(x+dx)g(x)dx

#导数的定义
dx = 0.00001
def deriv(g):
    return lambda x:(g(x+dx)-g(x))/dx

>>>deriv(lambda x:x*x*x)(5)
>>>75.00014999664018 

如果g(x)是一个可微函数,那么方程根g(x)=0的解就是函数 f(x)=xg(x)Dg(x) 的一个不动点

#牛顿转换
def newton_transform(g):
    return lambda x:x-g(x)/deriv(g)(x)
#牛顿法
def newton_method(g,guess):
    return fixed_point(newton_transform(g),guess)

#牛顿法求平方根,相当于求$g(y)=y^2-x$的g(y)=0的解
def sqrt(x):
    return newton_method(lambda y:y*y-x,1.0)

抽象层次高代码越容易复用,需要一步一步的理解函数直接调用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值