从这篇文章开始,我打算稍微聊一下函数式编程,以及Python中对函数式编程有哪些支持,我们在Python中如何应用函数式编程。虽然不会对函数式编程做一个很详尽的讲述,但也会做一个简短的系列性讲述,以便于Python爱好者能够对Python这门支持多个编程范式的语言,能够使用地更加得心应手。
本文作为函数式编程系列的开篇,希望能对函数式编程做一个系统性介绍,从全局上解决函数式编程是什么,为什么要使用函数式编程的问题。
本文的主要内容有:
1、编程语言与编程范式的关系
2、为啥要用函数式编程
3、函数式编程的核心概念
编程语言与编程范式的关系从Python系列文章写到目前,我们主要涉及过的编程范式有:过程式编程、面向对象编程,以及今天开始介绍的函数式编程。更多的编程范式的介绍,可以看上一篇文章的内容。
关于编程语言和编程范式的关系,其实,前面也介绍过。编程范式是以几个核心编程理念构建的一套组织程序的行为规范,应用编程范式就是在组织程序的过程中,践行这些核心理念。
所以,编程范式与编程语言的关系有:
1、编程范式是脱离于具体的编程语言而独立存在的,是组织程序所需要遵循的理念、原则的一个集合。
2、编程语言的设计者决定了该语言对编程范式的支持,一门编程语言可以完全支持某一种编程范式,也可以部分支持某一种编程范式。
3、大部分编程语言对过程式编程范式都是完全支持的,因为,真正完成计算过程的处理器硬件本身不是函数式的,严格意义上也不是面向对象的,CPU实际上是过程式的。
说回我们一直在介绍的主角——Python,是一门典型的支持多范式的编程语言。过程式编程范式的支持可以认为是大部分编程语言默认支持的,所以,Python也是完全支持的。一切接对象的设计理念,使得Python对面向对象编程范式也是完全支持的。Python中的一些特性、工具、模块,使得我们可以进行函数式编程,但是,Python并不完全支持函数式编程,所以,跟纯函数式编程语言还是有所区别的,不过并不影响我们进行函数式编程的尝试与实践。
需要特别说明的是,Python作为一门多范式的编程语言,使得我们可以根据具体的业务场景,选择、甚至组合不同编程范式的优势,从而更加高效地进行程序的组织,有效支持业务需求的扩展。
为啥要用函数式编程没有哪种编程范式一定优于其他编程范式,对函数式编程比较陌生的同学,首先需要解决的不是如何学的问题,而是是“为什么”的问题。过程式编程或者面向对象编程很好,完全够用的话,其实是没有必要学习编程式范式的。
接下来,我来试着论述一下函数式编程的好处。
有位计算机科学领域的大佬说过,“编程是一种让他人了解你想让电脑做什么的艺术”。
编程人员的实际工作中,只有很少的时间是在编写新的代码,与编码相关的工作时间中,绝大部分的时间是在阅读自己的或者别人的代码,或者是对现有的代码进行更新、维护。
所以,程序的可读性很关键。使用函数式编程范式进行程序的组织时,程序会更加简洁、可读。
此外,程序的可读性还在于相关业务逻辑的梳理的便捷性。同样的一套业务逻辑,使用函数式编程时,所带来的最大的好处是“确定性”。这些确定性来自于函数式编程中“不可变性”和“纯函数”的特性,因为在函数式的代码中,任何一个变量的状态都是确定的,任何函数的功能、影响也都是确定的。
函数式编程通过在函数中定义表达式和对表达式求值完成计算。它尽量避免由于状态变化和使用可变对象引入复杂性,让程序变得简洁明了。
由于确定性,函数式编程范式所组织的代码是易于阅读、易于调试和维护的。
如果你有读自己历史的代码或者读别人的代码,很恶心也要坚持读下去的经历,那么,在某些场景下,函数式编程一定是一个更好的选择。
函数式编程的核心概念相较于过程式编程、面向对象编程,函数式编程虽然是较晚才被提及的,但是,其实是这三个范式里面,最先发明的。
函数式编程的概念是基于与阿兰·图灵同时代的数学家Alonzo Church在1936年发明的lambda演算的直接衍生物。
1、不可变性(Immutability)
lambda演算的一个核心思想就是不可变性——某个符号所对应的值是永远不变的,所以,从理论上来说,函数式编程语言中应该是没有赋值语句的。大部分函数式编程语言只允许在非常严格的限制条件下,才可以更改某个变量的值。
所以,函数式编程的一个最核心的概念就是——不可变性,概括来说,就是函数式编程对程序中的赋值进行了限制和规范。
2、纯函数(Pure Function)
纯函数,是函数式编程的第二个核心概念。纯函数具有如下特征:
a、该函数是幂等的:给定相同的输入参数,函数总是返回精确的相同的结果。
b、该函数没有副作用:函数不以任何方式依赖或者修改外部世界的状态。副作用的例子我们在过程式编程或者面向对象编程中经常见到,比如:改变全局变量、写入到硬盘、读取用户控制台的输入等。
3、函数作为一等公民(First-Class and Higher-Order Functions)
在函数式编程中,函数被视为一等公民,可以像变量一样被传递和使用。而且,当一个函数能够接收函数作为参数,或者返回一个函数,则该函数自然而然就成了一个高阶函数。这些内容,其实我们前面已经反复提及。
4、函数组合(Function Composition)
函数组合是指将多个函数组合起来形成一个新的函数,使得输出一个函数的结果作为输入传递给另一个函数。函数组合有助于更加清晰地快速构建复杂的操作流程。
5、惰性求值(Lazy Evaluation)
惰性求值是指需要结果时才计算表达式的值,而不是在表达式定义时就进行计算。在Python中,可以通过生成器和迭代器实现惰性求值。这些内容,我们在后面会逐步介绍。
简单小结一下,函数式编程的核心概念主要有:
1、不可变性,简单来说就是不能重复赋值。
2、纯函数,就是具备幂等性、无副作用的函数。
3、函数作为一等公民,可以像变量一样被使用。
4、函数组合,通过将单一职责的纯函数进行组合,从而实现更加复杂、强大的功能。
5、惰性求值,在需要的时候才真正计算,从而提高性能。
概括来说,函数式编程可以这样理解:以函数为基本单元,没有变量(更准确地说是不能重复赋值)也没有副作用的编程方式。但是从更深的层次上看,它彻底隔离了可变性,变量或者状态默认就是不可变的,如果要变化,则必须经过合理设计的专门机制来实现。所以,它也避免了死锁、状态冲突等众多麻烦。
总结本文首先简单介绍了编程范式的概念,然后梳理了编程语言与编程范式的关系。在此基础上,引入了函数式编程这一范式,着重介绍了为什么要学习函数式编程。最后,系统梳理了函数式编程的核心概念,从而对后续学习函数式编程有一个纲领性的了解。
感谢您的拨冗阅读,希望对您学习Python有所帮助。