美文网首页
python进阶-函数式编程库toolz用法介绍-part2

python进阶-函数式编程库toolz用法介绍-part2

作者: DATA_KENGOU | 来源:发表于2018-08-24 14:19 被阅读0次

      在第一部分简单介绍了python的函数式编程基本方法后,从这部分开始将开始更深入的学习toolz的使用方法。话不多说,下面开始上示例代码。
      将上一部分的函数拿来继续用

    def add(x, y):
        return x + y
    
    def mul(x, y):
        return x * y
    
    def lesser(x, y):
        if x < y:
            return x
        else:
            return y
    
    def greater(x, y):
        if x > y:
            return x
        else:
            return y
    

      首先是accumulate的用法,功能类似于numpy的累加,不过操作(加、乘或其他计算)具体由传入的第一个参数来决定;又可以看出和reduce相近,只不过reduce只返回最后的结果

    import numpy as np
    X[X>=10].cumsum()
    # >>>array([ 10,  21,  33,  46,  60,  75,  91, 108, 126, 145], dtype=int32)
    
    data = range(10, 20)
    list(accumulate(add, data))
    # >>>[10, 21, 33, 46, 60, 75, 91, 108, 126, 145]
    
    from functools import reduce
    reduce(add,data)
    # >>>145
    

      继续来看mapreduceaccumulate的更灵活的一些用法,

    data1 = [1, 2, 3, 4, 5]
    data2 = [10, 20, 30, 40, 50]
    list(map(add, data1, data2))
    # >>>[11, 22, 33, 44, 55]
    
    reduce(lesser, [5, 3, 2, 7, 3], 999999999) # 注意第三个参数为初值
    # >>> 2
    reduce(lesser, [5, 3, 2, 7, 3], 1)
    # >>> 1
    
    list(accumulate(lesser, [5, 3, 2, 7, 3]))
    # >>> [5, 3, 2, 2, 2]
    

      可以看出mapreduceaccumulate的第一个参数需要传入一个两个参数的函数(类似于双目运算符)。
      到现在为止,热身活动已经结束了,开始介绍下面重要的一个概念,函数的柯里化(Currying,中文翻译还是有些怪,看英文有可能突然想到投3分的库里啊)。首先介绍python中的几种处理高阶函数(higher order function)的方式,高阶函数可以简单理解为函数的函数,即函数可以当做变量传来传去,从而达到更灵活的用法。

    #方式1 普通函数
    def cumsum(data):
        return accumulate(add, data)
    #方式2 匿名函数
    cumsum = lambda data: accumulate(add, data)
    #方式3 偏函数
    from functools import partial
    cumsum = partial(accumulate, add)
    #三种方式都是下面一个结果
    list(cumsum(data))
    # >>>[10, 21, 33, 46, 60, 75, 91, 108, 126, 145]
    

      我们用高阶函数的方式实现了一个输出每步累加值的函数cumsum,除了普通函数的方式外,另外两种方式个人感觉都还算pythonic,选哪种看个人喜好了。
      同样的功能,更函数式的方式,下面轮到神射手curry出场了!

    from toolz import curry
    mul_cur = curry(mul)
    mul_cur(2)  # 传入参数后返回一个函数,然后就剩下一个参数可传了
    # >>> <function mul at 0x00000000072A1EA0>
    mul_cur(2)(3)
    # >>> mul_cur(2)(3)
    
    # 方式4 currying的方式
    accumulate = curry(accumulate)
    cumsum = accumulate(add)
    

      用斐波那契函数的例子来说明一下稍微复杂一点的情况,生成斐波那契数列的前10个数字,但是又不想(或者不能)改变fib函数的前提下(虽然我知道这样执行效率低),通过curry来得到了一个新的函数,相比于直接用列表展开或者每次都用map去做的话,肯定是更加方便快捷,并且通过新的函数名提高了程序的可读性。

    def fib(n):
        a, b = 0, 1
        for i in range(n):
            a, b = b, a + b
        return b
    fib(9)
    # >>> 55
    map = curry(map)
    fibMany = map(fib)
    list(fibMany(range(10)))
    # >>> [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
    

      最后,告诉大家其实没必要每次都用curry去“包裹”一次maptoolz里面做好准备工作,提供了相关的柯里化好的函数。

    from toolz.curried import map, accumulate, reduce, filter  
    # 函数很多就不一一列举了, 这些都等价于下面手动柯里化
    from toolz import map, curry
    map = curry(map)
    

      未完待续 ...

    相关文章

      网友评论

          本文标题:python进阶-函数式编程库toolz用法介绍-part2

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