美文网首页
建立函数抽象

建立函数抽象

作者: 彩色系 | 来源:发表于2017-03-16 11:57 被阅读0次

    什么是好的抽象?

    比如这样一个函数:

    def accumulate(combiner, base, n, term):
        total, k=base, 1
        while k<=n:
            total,k = combiner(total, term(k)), k+1
        return total
    

    利用这个函数能够构建出不同的符合这个抽象的函数。

    比如 将0-x间的不同特征的数相加:

    term函数可以是平方,立方
    def summation_using_accumulate(n, term):
        return accumulate(add, 0, n, term)
    

    相乘:

    def product_using_accumulate(n, term):
        return accumulate(mul, 1, n, term)
    

    将0-x间的数过滤出来相加可以这样子做:

    def filtered_accumulate(combiner, base, pred, n,term):
        def combiner_if(x,y):
            if pred(y):
                return combiner(x,y)
            else:
                return x
        return accumulate(combiner_if, base, n, term)
    

    利用一个高阶函数,pred是过滤的规则
    比如只要偶数
    odd = lambda x: x%2==1
    filtered_accumulate(add, 0, odd, x, term)

    再比如对一个函数多次调用

    repeated(square, 2)(5) = square(square(5))
    利用高阶函数能够很简单实现。
    def repeated(f, n):
        def inner(x):
            nonlocal n
            if n == 0:
                return x
            result = x
            while n > 0:
                result = f(result)
                n -= 1
            return result
        return inner
    但是仔细想想,似乎能够用上面的那个函数来写 可以这样做:
    定义一个高阶函数
    def compose(f, g):
        def h(x):
            return f(g(x))
        return h
    def repeated(f, n):
        return accumulate(compose, lambda x:x, n,lambda k:f)
    
    发现 要进行0-n次term计算,用compose来组合起来 都可以用accumuldate这个抽象
    比如上面这个例子 对x进行term计算,然后组合.
    

    lambda 表达式,注意它是运行时绑定的。

    >>> a=3
    >>> b=2
    >>> c = lambda a,b:a+b
    >>> b-=a
    >>> c(a,b)
    2
    

    递归:

    以常见的斐波那契数列来说
    树形递归,复杂度最高,有很多的重复计算。
    从f(1)=1开始的。
    def fib(n):
        if n<2:
            return n
        return fib(n-1)+fib(n-2)
    我们可以这样子写,利用数来保存中间变量,不用重复计算。
    def fib2(a,b,n):
        if n > 0:
            return fib2(b,a+b,n-1)
        return a
    

    装饰器:

    @decorator
    def func
    相当于decorator(func)
    能够用装饰器做很多事情。比如:
    定义一个memo缓存函数,来优化上面的fib
    def memo(f):
        cache = {}
        def helper(*args):
            if args not in cache:
                cache[args]=f(args)
            return cache[args]
        return helper
    利用了一个缓存来保存变量。
    

    总结 要多思考建立好的函数抽象。

    函数编码原则:

    1. 函数名 称应 该小写 , 以下划 线分隔。 提倡描述性的名 称。
    2. 函数名 称通常反映解释器 向参数应 用 的操作( 例如 print 、 add 、 square ) , 或者结
      果( 例 如 max 、 abs 、 sum ) 。
    3. 参数名 称应 小写 , 以下划 线分隔。 提倡单个词的名 称。
    4. 参数名 称应 该反映参数在函数中 的作用 , 并不仅仅是满足的值的类型 。
    5. 当 作用 非常明 确时, 单个字母的参数名 称可以接受, 但是永远不要使用 l ( 小写 的 L )
      和 O ( 大写 的 o ) , 或者 I ( 大写 的 i ) 来避免和数字混淆。

    函数设计原则

    一个函数只完成一个功能,遵循dry原则。
    写函数帮助文档,利用doctest进行测试。
    调试的一些原则:
    逐步测试,隔离错误,追踪到最小的代码片。检查假设。

    来自http://www.97up.cn/post/83

    相关文章

      网友评论

          本文标题:建立函数抽象

          本文链接:https://www.haomeiwen.com/subject/roodnttx.html