在这篇文案里,你将学会什么是函数范式以及怎样运用Python进行函数式编程。你亦将认识列表推导和其它形式的推导。
函数范式
在命令式范式中,经过为计算机供给一系列指令而后执行它们来完成任务。在执行这些指令时,能够改变某些状态。例如,假设你最初将A设置为5,而后更改A的值。此时在变量内部值的道理上,你改变了A的状态。
在函数式范式中,你不消告诉计算机做什么而是告诉他这个东西是什么。例如数字的最大公约数是什么,从1到n的乘积是什么等等。
因此呢,变量不可变化。一旦你设置了一个变量,它就永远保持这种状态(重视,在纯函数式语言中,它们不是变量)。因此呢,函数式编程无副功效。副功效指的是函数改变它自己以外的东西。让咱们看有些典型Python代码的示例:
这段代码的输出是5。在函数式范式中,改变变量是一个很大的禁忌,并且拥有影响其范围之外事物的功能亦是一个很大的禁忌。函数独一能做的便是计算有些东西并将其做为结果返回。
此刻你可能会想:“无变量,无副功效?为何这般好?“这个问题问得好,我相信大都数人对此感到疑惑。
倘若运用相同的参数调用函数两次,则保准返回相同的结果。倘若你已然学习了数学函数,你就会晓得这个好处。这叫作为参照透明度。因为函数无副功效,倘若你正在构建一个计算某些事情的程序,你能够加速程序。倘若每次调用func(2)都返回3,咱们能够将它存储在表中,这能够防止程序重复运行相同的功能。
一般,在函数式编程中,咱们不运用循环。咱们运用递归。递归是一个数学概念,一般寓意着“自我调用”。运用递归函数,该函数将其自己做为子函数重复调用。这是Python中递归函数的一个很好的例子:
有些编程语言亦拥有惰性。这寓意着她们直到最后一秒才计算或做任何事情。倘若你编写有些代码来执行2 + 2,函数程序只会在你真正必须运用结果时计算出来。咱们火速就会在Python中探索惰性。
Map
为了理解,咱们先来瞧瞧迭代是什么。一般能够迭代的对象是列表或数组,但Python有许多区别的类型能够迭代。你乃至能够创建自己的对象,这些对象能够经过实现魔术办法进行迭代。魔术办法就像是一个API,能够帮忙你的对象变得更加Pythonic。您必须实现2个魔术办法才可使对象作为可迭代的:
第1个魔术办法“__iter__”(注:这儿是双下划线)返回迭代对象,这一般在循环起始时运用。”__next__“返回下一个对象。
让咱们快速进入一个终端调用上面的代码:
运行将会打印出
在Python中,迭代器是一个仅有__iter__魔术办法的对象。这寓意着您能够拜访对象中的位置,但不可遍历该对象。有些对象将拥有魔术办法__next__而不是__iter__魔术办法,例如集合(在本文后面讨论)。针对本文,咱们假设咱们接触的所有内容都是可迭代的对象。
此刻咱们晓得什么是可迭代对象了,让咱们回到map函数。 map函数准许咱们将函数应用于iterable中的每一项。 Map必须2个输入,它们分别是要应用的函数和可迭代对象。
假设咱们有一个数字列表,如下所示:
咱们想要对每一个数字进行平方,咱们能够编写如下代码:
Python中函数式的函数是拥有惰性的。倘若咱们不运用“list”,该函数将存储iterable的定义,而不是列表本身。咱们必须知道告诉Python“把它变成一个列表”供咱们运用。
在Python中忽然从非惰性求值转向惰性求值有点奇怪。倘若你在函数式思维方式中思虑得更加多,而不是命令式思维方式,那样你最后会习惯它。
此刻写一个像“square(num)”这般的普通函数虽然很好,但却是不对的。咱们必要定义一个完整的函数才可在map中运用它?好吧,咱们能够运用lambda(匿名)函数在map中定义一个函数。
Lambda表达式
lambda表达式是一个仅有一行的函数。举个例子,这个lambda表达式对给定的数字进行平方:
让咱们运行它:
这看起来不像一个函数吗?
嗯,这有点令人困惑,但能够解释。咱们将有些东西分配给变量“square”。那这个呢:
告诉Python这是一个lambda函数,输入叫做x。冒号之后的任何内容都是您对输入所做的操作,它会自动返回结果。
简化咱们的square程序到仅有一行代码,咱们能够这般做:
因此在lambda表达式中,所有参数都在左边,你要用它们做的东西在右边。它有点乱。但事实是,编写仅有其他函数式程序员才可阅读的代码会有必定的乐趣。另外,运用一个函数并将其转换为一行代码是非常酷的。
Reduce
Reduce是一个将迭代变成一个东西的函数。一般,你能够在列表上运用reduce函数执行计算以将其减少到一个数字。 Reduce看起来像这般:
咱们经常会运用lambda表达式做为函数。
列表的乘积是每一个单独的数字相乘。要做到这一点你将编写如下代码:
然则运用reduce你能够这般写:
得到相同的功能,代码更短,并且在运用函数式编程的状况下更整洁。(注:reduce函数在Python3中已不是内置函数,必须从functools模块中导入)
Filter
filter函数采用可迭代的方式,并过滤掉你在该可迭代中不必须的所有内容。
一般,filter必须一个函数和一个列表。它将函数应用于列表中的每一项,倘若该函数返回True,则不执行任何操作。倘若返回False,则从列表中删除该项。
语法如下:
让咱们看一个小例子,无filter咱们会写:
运用filter,能够这般写:
高阶函数
高阶函数能够将函数做为参数并返回函数。一个非常简单的例子如下:
第二个返回函数的例子:
开头我说过纯函数式编程语言无变量。更高阶的函数使这变得更易。
Python中的所有函数都是一等百姓。一等百姓被定义为拥有以下一个或多个特征: 在运行时创建在数据结构中分配变量或元素做为函数的参数传递做为函数的结果返回Python中的所有函数都能够用作高阶函数。Partial application
Partial application(亦叫作为闭包)有点奇怪,但非常酷。您能够在不供给所需的所有参数的状况下调用函数。让咱们在一个例子中看到这一点。咱们想要创建一个函数,它接受2个参数,一个基数和一个指数,并返回指数幂的基数,如下所示:
此刻咱们想要一个专用的平方函数,运用幂函数计算出数字的平方:
这有效,但倘若咱们想要一个立方体功能呢?或求四次方的功能呢?咱们能够继续写下它们吗?好吧,你能够。但程序员很懒的。倘若你一遍又一遍地重复一样的事情,这显示有一种更快的办法来加快速度,这将使你再也不重复。咱们能够在这儿运用闭包。让咱们看一个运用闭包的square函数的示例:
是不是很酷!咱们能够只运用1个参数来调用必须2个参数的函数。
咱们还能够运用一个循环来生成一个幂函数,该函数实现从立方体始终到1000的幂。
函数式编程不是pythonic
您可能已然重视到了,咱们想要在函数式编程中做的非常多事情都围绕着列表。除了reduce函数和闭包之外,您看到的所有函数都会生成列表。 Guido(Python之父)不爱好Python中的函数式,由于Python已然有了自己生成列表的办法。
倘若你在Python的交互环境下写入”import this“,你将会得到:
这是Python之禅。这是一首关于Pythonic寓意着什么的诗。咱们想要触及的部分是:
There should be one — and preferably only one — obvious way to do it.(应该尽可能找到一种,最好是独一一种显著的处理方法)
在Python中,map和filter能够执行与列表推导(下面讨论)相同的操作。这打破了Python之禅的一个规则,因此呢函数式编程的这些部分不被视为“pythonic”。
另一个专题是Lambda。在Python中,lambda函数是一个普通函数。 Lambda是语法糖。这两种说法是等价的。
普通函数能够执行lambda函数能够执行的所有操作,但它不可以相反的方式工作。 lambda函数不可完成普通函数能够执行的所有操作。
这是一个简短的论证,为何函数式编程不可很好地适应全部Python生态系统。你可能已然重视到我之前说到了列表推导,咱们此刻将讨论它们。
列表推导
前面,我说到过你能够用map或filter做的任何事情,你能够用列表推导。列表推导是一种在Python中生成列表的办法。语法是:
让咱们对列表中的每一个数字进行平方,例如:
咱们能够看到怎样将函数应用于列表中的每一项。咱们怎样应用filter呢?瞧瞧前面的代码:
咱们能够将其转换成一个列表推导,像这般:
列表支持if这般的语句。您再也不必须将一百万个函数应用于某些东西以得到您想要的东西。事实上,倘若你想尝试生成某种列表,那样运用列表推导看起来会更清晰,更易。倘若咱们想要将列表中每一个0以下的数字平方怎么办?有了lambda,map和filter你会写:
这似乎很长很繁杂。经过列表推导,它只是:
列表推导仅适用于列表。map,filter适合任何可迭代的对象,那样这有什么用呢?你能够对你遇到的任何可迭代对象运用任何推导。
其他推导
你能够为任何可迭代对象创建一个推导。
能够运用推导生成任何可迭代的对象。从Python 2.7起始,您乃至能够生成字典(hashmap)。
倘若它是可迭代的,则能够生成它。让咱们看一下最后一组的例子。
set是一个元素列表,在该列表中无元素重复两次。set中的元素无次序。
您可能会重视到set(集合)与dict(字典)拥有相同的花括号。 Python非常聪明。按照你是否为dict供给值,它会晓得你是在写dict推导还是set推导。
总结
函数式编程美观而纯粹。函数式代码能够很干净,但亦可能很乱。有些Python程序员不爱好Python中的函数式编程。但我认为,你应该在处理问题时,运用最佳工具。
英文原文:
https://qiniumedia.freelycode.com/vcdn/1/优秀文案长图 2/learnfunctionprogramin10minutes.pdf
译者:xiaocai
|