Python函数式编程

Python函数式编程


函数式编程是近些年来大家愈发重视的一种编程范式,python和ruby等语言中也有了各种函数式语言的特性,如lambda演算等,因此掌握函数式编程尤为重要。笔者将通过对内建函数map和reduce的实现来简单讲述函数式编程的一些概念。

  • map函数:
    map(func,seq1[,seq2…])
    map函数将func作用于seq中的每一个元素并用一个列表给出返回值。
    下面是我自己的map实现:
def MyMap(f,seq):
    def iter(n,l):
        if(n < 0):
            l.reverse()
            return l
        else:
            l.append(f(seq[n]))
            return iter(n-1,l)
    return iter(len(seq)-1,[])

r = MyMap(lambda x:x+1,[1,2,3,4,5,6,7,8,9])
print(r)

在这个函数里,我定义了另一个函数iter,这样在任意位置定义函数的写法也是函数式语言的特性之一,因为函数是“一等公民”。
这里的iter用了尾递归的写法,之所以这么写是为了让函数更加“函数式”,因为函数式语言中没有循环语句。
不过因为python的特性,如l.reverse()这样的语句是没有返回值的,所以无法写入return中,只能用命令式的方法表达。
我们的目的是让MyMap返回一个list,而这个list又由iter来编辑,所以就让iter在结束的时候返回list,并且把iter写在MyMap返回值中,从而传递list。

在倒数第二行,我用了一个lambda函数(匿名函数),这个函数的意义在于方便定义那种只用一次的函数,不用专门为它取名字,这一特性让程序更加简洁干净。

  • reduce函数
    reduce(func,seq[,init])
    reduce函数即化简,它每次迭代,将上一次的迭代结果与下一个元素一同执行一个二元的func函数。
    自己的实现如下:
def MyReduce(f,seq):
    def iter(n):
        if(n < 0):
            return 0
        else:
            return seq[n]+iter(n-1)
    return iter(len(seq)-1)

这个函数和上面的思路类似,不过有一点不一样,那就是上一个函数中的辅助函数使用了尾递归,而这个是普通递归。
为什么要说递归呢,还是因为前面提到的,函数式语言中没有循环,所以熟练运用递归并优化递归就是一个必须技能,学习函数式编程也不能跳过递归的学习。
仔细观察两个函数会发现,第一个函数的返回值是

iter(len(seq)-1,[])

而第二个是

seq[n]+iter(n-1)

区别在第一个返回值只有函数本身,而第二个则包含了一个seq[n]+。
如果n非常大,那么第二种写法将会非常低效,因为函数需要运行到n=0后不断往回走不断与seq[n]相加。而第一种写法则没有返回的过程,运行更快。
同时,在第二种写法中,因为最后注定要往回走,所以前面的数据必须保留,这样n非常大的时候保留的数据就会非常多,多到一定程度后会栈溢出。而第一种写法将数据全部储存在了变量中,不会存在栈溢出的问题。

上面就是python函数式编程中一些比较基础的东西:递归、匿名函数和返回值。这些不仅可以用在python中,其它任何一个支持函数式的语言中都可以用到。

在学习python函数式编程的时候,不要关注python,要关注函数,后者才是真正的重点。

函数式编程也远不止是上面说的这些,还有continuation passing style(CPS),柯里化,闭包等技术,有兴趣深入学习的话可以了解一下scheme等“更函数”的语言,python支持的函数式编程并不能完全体现函数式编程的思想。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值