10分钟学会python函数式编程

Souleigh ✨ 等级 364 0 0

在这篇文章里,你将学会什么是函数范式以及如何使用Python进行函数式编程。你也将了解列表推导和其它形式的推导。

函数范式

在命令式范式中,通过为计算机提供一系列指令然后执行它们来完成任务。在执行这些指令时,可以改变某些状态。例如,假设你最初将A设置为5,然后更改A的值。这时在变量内部值的意义上,你改变了A的状态。

在函数式范式中,你不用告诉计算机做什么而是告诉他这个东西是什么。比如数字的最大公约数是什么,从1到n的乘积是什么等等。

因此,变量不能变化。一旦你设置了一个变量,它就永远保持这种状态(注意,在纯函数式语言中,它们不是变量)。因此,函数式编程没有副作用。副作用指的是函数改变它自己以外的东西。让我们看一些典型Python代码的示例:

10分钟学会python函数式编程

这段代码的输出是5。在函数式范式中,改变变量是一个很大的禁忌,并且具有影响其范围之外事物的功能也是一个很大的禁忌。函数唯一能做的就是计算一些东西并将其作为结果返回。

现在你可能会想:“没有变量,没有副作用?为什么这样好?“这个问题问得好,我相信大多数人对此感到疑惑。

如果使用相同的参数调用函数两次,则保证返回相同的结果。如果你已经学习了数学函数,你就会知道这个好处。这称为参照透明度。由于函数没有副作用,如果你正在构建一个计算某些事情的程序,你可以加速程序。如果每次调用func(2)都返回3,我们可以将它存储在表中,这可以防止程序重复运行相同的功能。

通常,在函数式编程中,我们不使用循环。我们使用递归。递归是一个数学概念,通常意味着“自我调用”。使用递归函数,该函数将其自身作为子函数重复调用。这是Python中递归函数的一个很好的例子:

10分钟学会python函数式编程

有些编程语言也具有惰性。这意味着他们直到最后一秒才计算或做任何事情。如果你编写一些代码来执行2 + 2,函数程序只会在你真正需要使用结果时计算出来。我们很快就会在Python中探索惰性。

Map

为了理解,我们先来看看迭代是什么。通常可以迭代的对象是列表或数组,但Python有许多不同的类型可以迭代。你甚至可以创建自己的对象,这些对象可以通过实现魔术方法进行迭代。魔术方法就像是一个API,可以帮助你的对象变得更加Pythonic。您需要实现2个魔术方法才能使对象成为可迭代的:

10分钟学会python函数式编程

第一个魔术方法“__iter__”(注:这里是双下划线)返回迭代对象,这通常在循环开始时使用。”__next__“返回下一个对象。

让我们快速进入一个终端调用上面的代码:

10分钟学会python函数式编程

运行将会打印出

10分钟学会python函数式编程

在Python中,迭代器是一个只有__iter__魔术方法的对象。这意味着您可以访问对象中的位置,但不能遍历该对象。一些对象将具有魔术方法__next__而不是__iter__魔术方法,例如集合(在本文后面讨论)。对于本文,我们假设我们接触的所有内容都是可迭代的对象。

现在我们知道什么是可迭代对象了,让我们回到map函数。 map函数允许我们将函数应用于iterable中的每一项。 Map需要2个输入,它们分别是要应用的函数和可迭代对象。

10分钟学会python函数式编程

假设我们有一个数字列表,如下所示:

10分钟学会python函数式编程

我们想要对每个数字进行平方,我们可以编写如下代码:

10分钟学会python函数式编程

Python中函数式的函数是具有惰性的。如果我们不使用“list”,该函数将存储iterable的定义,而不是列表本身。我们需要明确告诉Python“把它变成一个列表”供我们使用。

在Python中突然从非惰性求值转向惰性求值有点奇怪。如果你在函数式思维方式中考虑得更多,而不是命令式思维方式,那么你最终会习惯它。

现在写一个像“square(num)”这样的普通函数虽然很好,但却是不对的。我们必须定义一个完整的函数才能在map中使用它?好吧,我们可以使用lambda(匿名)函数在map中定义一个函数。

Lambda表达式

lambda表达式是一个只有一行的函数。举个例子,这个lambda表达式对给定的数字进行平方:

10分钟学会python函数式编程

让我们运行它:

10分钟学会python函数式编程

这看起来不像一个函数吗?

嗯,这有点令人困惑,但可以解释。我们将一些东西分配给变量“square”。那这个呢:

10分钟学会python函数式编程

告诉Python这是一个lambda函数,输入叫做x。冒号之后的任何内容都是您对输入所做的操作,它会自动返回结果。

简化我们的square程序到只有一行代码,我们可以这样做:

10分钟学会python函数式编程

所以在lambda表达式中,所有参数都在左边,你要用它们做的东西在右边。它有点乱。但事实是,编写只有其他函数式程序员才能阅读的代码会有一定的乐趣。此外,使用一个函数并将其转换为一行代码是非常酷的。

Reduce

Reduce是一个将迭代变成一个东西的函数。通常,你可以在列表上使用reduce函数执行计算以将其减少到一个数字。 Reduce看起来像这样:

10分钟学会python函数式编程

我们经常会使用lambda表达式作为函数。

列表的乘积是每个单独的数字相乘。要做到这一点你将编写如下代码:

10分钟学会python函数式编程

但是使用reduce你可以这样写:

10分钟学会python函数式编程

获得相同的功能,代码更短,并且在使用函数式编程的情况下更整洁。(注:reduce函数在Python3中已不是内置函数,需要从functools模块中导入)

Filter

filter函数采用可迭代的方式,并过滤掉你在该可迭代中不需要的所有内容。

通常,filter需要一个函数和一个列表。它将函数应用于列表中的每一项,如果该函数返回True,则不执行任何操作。如果返回False,则从列表中删除该项。

语法如下:

10分钟学会python函数式编程

让我们看一个小例子,没有filter我们会写:

10分钟学会python函数式编程

使用filter,可以这样写:

10分钟学会python函数式编程

Python作为一门不断发展与普及的语言,还在不断更新中。在学习时,建议找一些学习伙伴一起来学习和讨论,效果更佳。如果想学习Python,欢迎加入Python学习交流群(627012464),一起督促,一起学习。里面有开发工具,很多干货和技术资料分享!

高阶函数

高阶函数可以将函数作为参数并返回函数。一个非常简单的例子如下:

10分钟学会python函数式编程

第二个返回函数的例子:

10分钟学会python函数式编程

开头我说过纯函数式编程语言没有变量。更高阶的函数使这变得更容易。

Python中的所有函数都是一等公民。一等公民被定义为具有以下一个或多个特征:

在运行时创建

在数据结构中分配变量或元素

作为函数的参数传递

作为函数的结果返回

Python中的所有函数都可以用作高阶函数。

Partial application

Partial application(也称为闭包)有点奇怪,但非常酷。您可以在不提供所需的所有参数的情况下调用函数。让我们在一个例子中看到这一点。我们想要创建一个函数,它接受2个参数,一个基数和一个指数,并返回指数幂的基数,如下所示:

10分钟学会python函数式编程

现在我们想要一个专用的平方函数,使用幂函数计算出数字的平方:

10分钟学会python函数式编程

这有效,但如果我们想要一个立方体功能呢?或者求四次方的功能呢?我们可以继续写下它们吗?好吧,你可以。但程序员很懒的。如果你一遍又一遍地重复同样的事情,这表明有一种更快的方法来加快速度,这将使你不再重复。我们可以在这里使用闭包。让我们看一个使用闭包的square函数的示例:

10分钟学会python函数式编程

是不是很酷!我们可以只使用1个参数来调用需要2个参数的函数。

我们还可以使用一个循环来生成一个幂函数,该函数实现从立方体一直到1000的幂。

10分钟学会python函数式编程

函数式编程不是pythonic

您可能已经注意到了,我们想要在函数式编程中做的很多事情都围绕着列表。除了reduce函数和闭包之外,您看到的所有函数都会生成列表。 Guido(Python之父)不喜欢Python中的函数式,因为Python已经有了自己生成列表的方法。

如果你在Python的交互环境下写入”import this“,你将会得到:

10分钟学会python函数式编程

这是Python之禅。这是一首关于Pythonic意味着什么的诗。我们想要涉及的部分是:

There should be one — and preferably only one — obvious way to do it.(应该尽量找到一种,最好是唯一一种明显的解决方案)

在Python中,map和filter可以执行与列表推导(下面讨论)相同的操作。这打破了Python之禅的一个规则,因此函数式编程的这些部分不被视为“pythonic”。

另一个话题是Lambda。在Python中,lambda函数是一个普通函数。 Lambda是语法糖。这两种说法是等价的。

10分钟学会python函数式编程

普通函数可以执行lambda函数可以执行的所有操作,但它不能以相反的方式工作。 lambda函数不能完成普通函数可以执行的所有操作。

这是一个简短的论证,为什么函数式编程不能很好地适应整个Python生态系统。你可能已经注意到我之前提到了列表推导,我们现在将讨论它们。

列表推导

前面,我提到过你可以用map或filter做的任何事情,你可以用列表推导。列表推导是一种在Python中生成列表的方法。语法是:

10分钟学会python函数式编程

让我们对列表中的每个数字进行平方,例如:

10分钟学会python函数式编程

我们可以看到如何将函数应用于列表中的每一项。我们如何应用filter呢?看看前面的代码:

10分钟学会python函数式编程

我们可以将其转换成一个列表推导,像这样:

10分钟学会python函数式编程

列表支持if这样的语句。您不再需要将一百万个函数应用于某些东西以获得您想要的东西。事实上,如果你想尝试生成某种列表,那么使用列表推导看起来会更清晰,更容易。如果我们想要将列表中每个0以下的数字平方怎么办?有了lambda,map和filter你会写:

10分钟学会python函数式编程

这似乎很长很复杂。通过列表推导,它只是:

10分钟学会python函数式编程

列表推导仅适用于列表。map,filter适合任何可迭代的对象,那么这有什么用呢?你可以对你遇到的任何可迭代对象使用任何推导。

其他推导

你可以为任何可迭代对象创建一个推导。

可以使用推导生成任何可迭代的对象。从Python 2.7开始,您甚至可以生成字典(hashmap)。

如果它是可迭代的,则可以生成它。让我们看一下最后一组的例子。

10分钟学会python函数式编程

set是一个元素列表,在该列表中没有元素重复两次。

set中的元素没有顺序。

10分钟学会python函数式编程

您可能会注意到set(集合)与dict(字典)具有相同的花括号。 Python非常聪明。根据你是否为dict提供值,它会知道你是在写dict推导还是set推导。

总结

函数式编程美观而纯粹。函数式代码可以很干净,但也可能很乱。一些Python程序员不喜欢Python中的函数式编程。但我认为,你应该在解决问题时,使用最佳工具。

收藏
评论区

相关推荐

Python的环境搭建和下载
Python是一个跨平台、可移植的编程语言,因此可在windows、Linux和Mac OS X系统中安装使用。 安装完成后,你会得到Python解释器环境,可以通过终端输入python命令查看本地是否已经按照python以及python版本。这里有一点需要注意的是,如果没有将python的安装目录添加到环境变量中,会报错(python不是内部命令或外部命
15. Python 程序运行速度如何提高十倍?第一遍滚雪球学 Python 收工
本篇文章将给大家介绍 Python 多线程与多进程相关知识,学习完该知识点之后,你的 Python 程序将进入另一个高峰。 <center<font colorred缓解一下视疲劳</font</center 15. Python 程序运行速度如何提高十倍?第一遍滚雪球学 Python 收工(https://imghelloworld.oss
Python正则表达式
re正则表达式基础语法 | 表达式 |可匹配 |表达式 |可匹配 | ||||| | \r,\n | 代表回车和换行符 |\^ | 可匹配^本身| |\t|制表符|\$|匹配$符号本身| |\\|代表“\”本身|\.|匹配小数点“.”本身| | 表达式 | 可匹配 | ||| | \d | 任意一个数字,09中的任意一个 | |\
Python的新式类和旧式类
概述: Python中支持多继承,也就是一个子类可以继承多个父类/基类。当一个调用一个自身没有定义的属性时,它是按照何种顺序去父类中寻找的呢?尤其是当众多父类中都包含有同名的属性,这就涉及到新式类 和 经典类的区别。 多继承: class Food(object): 2 3 def __init__(self, name, col
Python新式类与经典类(旧式类)的区别
Python新式类与经典类(旧式类)的区别 Python中类分两种:旧式类和新式类: ➤新式类都从object继承,经典类不需要。 ➤新式类的MRO(method resolution order 基类搜索顺序)算法采用C3算法广度优先搜索,而旧式类的MRO算法是采用
原来Python绘图也可以这么漂亮,这次真的是学习到了!
(https://imghelloworld.osscnbeijing.aliyuncs.com/8830803f033eeed85783e9058cf08968.png) 作者:朱小五 来源:快学Python 👆人生苦短,快学Python! 最近看了一篇文章《一个牛逼的Python 可视化库:PyG2Plot》,可惜只是简单介
Python中JSON的基本使用_Just do it !
JSON (JavaScript Object Notation) 是一种轻量级的数据交换格式。Python3 中可以使用 json 模块来对 JSON 数据进行编解码,它主要提供了四个方法: dumps、dump、loads、load。 dump和dumps dump和dumps对python对象进行序列化。将一个Python对象
我的python总结
建议刚开始学习直接使用ANACONDAhttps://www.anaconda.com/download/配置python环境变量https://docs.python.org/3.6/using/cmdline.htmlenvvarPYTHONMALLOCPython PEP8导包顺序1. Python标准
Python编程基础(快速入门必看
Python编程基础一、Python语言基本语法 Python是一
python文件的第一行 #!/usr/bin/python3 是什么意思?
python文件的第一行代码通常在脚本语言的第一行会看到: !/usr/bin/env python或 !/usr/bin/python 首先要确定的一点是它不是注释。这两句话的目的都是指出你的python文件用什么可执行程序去运行它。1. !/usr/bin/python 是告诉操作系统执行这个脚本的时候,调用 /usr/bin 下的 python 解释
简述Python中常见的数据结构
「数仓宝贝库」,带你学数据!导读:Python中常见的数据结构有列表(list)、元组(tuple)、集合(set)、字典(dict)等,这些数据结构表示了自身在Python中的存在形式,在Python中可以输入type(对象)查看数据类型。 1列表 (1)创建列表 列表是Python内置的一种数据类型,它是一种有序的数据集合,是用于存储一连串
干掉公式 —— numpy 就该这么学
文 | 太阳雪 来源:Python 技术「ID: pythonall」机器学习和数据分析变得越来越重要,但在学习和实践过程中,常常因为不知道怎么用程序实现各种数学公式而感到苦恼,今天我们从数学公式的角度上了解下,用 python 实现的方式方法。 友情提示:不要被公式吓到,它们都是纸老虎关于 NumpyNumPy 是使用 Python 进行科学计算的基础软
10行Python代码自动清理电脑内重复文件,解放双手!
](https://mp.weixin.qq.com/mp/appmsgalbum?actiongetalbum&albumid1337012041701326848&bizMzI1MTUyMjc1Mgwechatredirect) 前言 大家好,又到了Python办公自动化系列。今天分享一个系统层面的自动化案例:「给定一个文件夹,使用Python检查
初窥 Python 的 import 机制
本文适合有 Python 基础的小伙伴进阶学习。 作者:pwwang一、前言本文基于开源项目: https://github.com/pwwang/pythonimportsystem补充扩展讲解,希望能够让读者一文搞懂 Python 的 import 机制。 1.1 什么是 import 机制?通常来讲,在一段 Python 代码中去执行引用另一个模块中
Python基础1——变量、判断、循环、字符串、列表
1 认识python 1.1 认识python计算机识别机器语言,机器语言由二进制0和1组成计算机要执行高级语言,转换方式 1. 编译 : C语言、C++、java。 一次性编译成可执行文件2. 解释 : 一行一行地解释python是解释型语言python解释器、pycharm编辑器举个例子:要给工地煮饭编译:把饭菜都做好,做成盒饭(.exe,.class