在本文中,您将了解什么是函数范型,以及如何在Python中使用函数式编程。python
在Python中,函数式编程中的map和filter能够作与列表相同的事情。这打破了Python的禅宗规则之一,所以函数式编程的这些部分不被认为是“Python式的”。程序员
可是因为函数式编程高阶编程的必经之路,因此咱们须要了解甚至熟练掌握。编程
咱们先对比一下编程中的命令范式两个概念:数组
在命令式范式中,您经过给计算机一个任务序列来完成任务,而后它执行这些任务。在执行它们时,它能够改变状态。网络
例如,假设你一开始把A设为5,而后你改变A的值,你有变量,在这个意义上,变量内部的值是变化的。闭包
在函数范型中,你不告诉计算机要作什么,而是告诉它是什么。例如:一个数的最大公约数是多少,从1到n的乘积是多少,等等。app
所以,变量不能改变。一旦你设置了一个变量,它就会一直保持这种状态(注意,在纯函数语言中它们不被称为变量)。框架
所谓"反作用"(side effect),指的是函数内部与外部互动(最典型的状况,就是修改全局变量的值),产生运算之外的其余结果。less
函数式编程强调没有"反作用",意味着函数要保持独立,全部功能就是返回一个新的值,没有其余行为,尤为是不得修改外部变量的值。机器学习
让咱们来看一个典型Python代码的例子:
a = 3 def some_func(): global a a = 5 some_func() print(a)
这段代码的输出是5。在函数范型中,改变变量是一个大禁忌,而让函数影响它们范围以外的东西也是一个大禁忌。函数惟一能作的就是计算并返回结果。
如今你可能会想:“没有变量,就没有反作用?”这有什么好处呢?
若是一个函数使用相同的参数被调用两次,那么它确定会返回相同的结果。由于函数没有反作用,若是你正在构建一个计算的程序,你能够加速这个程序。
若是程序知道func(2)等于3,咱们能够将其存储在一个表中。这能够防止程序在咱们已经知道答案的状况下重复运行相同的函数。
为了理解map,让咱们首先看看什么是iterables。
iterable是任何能够迭代的东西。一般这些是列表或数组,可是Python有许多不一样类型的迭代器。您甚至能够建立本身的对象,这些对象可使用Python中魔法方法进行迭代。
这里有两个方法:
class Counter: def __init__(self, low, high): # set class attributes inside the magic method __init__ # for "inistalise" self.current = low self.high = high def __iter__(self): # first magic method to make this object iterable return self def __next__(self): # second magic method if self.current > self.high: raise StopIteration else: self.current += 1 return self.current - 1
“魔法方法是python内置方法,不须要主动调用,存在的目的是为了给python的解释器进行调用,几乎每一个魔法方法都有一个对应的内置函数,或者运算符,当咱们对这个对象使用这些函数或者运算符时就会调用类中的对应魔法方法,能够理解为重写内置函数。”
第一个神奇的方法是用“__ iter__”返回迭代对象,一般在循环开始时使用。
若是咱们运行:
for c in Counter(3, 8): print(c)
那么将会输出:
345678
在Python中,迭代器是一个对象,它只有一个简单的魔法方法。这意味着您能够访问对象中的位置,但不能遍历对象。有些对象将使用方法__next__,如上面代码中第二个例子。
如今咱们知道了什么是可迭代对象,让咱们回到map函数。map函数容许咱们将一个函数应用到iterable中的每一个项。一般,咱们但愿对列表中的每一项都应用一个函数,可是要知道对于大多数迭代器来讲都是可能的。
Map接受两个输入,即要应用的函数和可迭代的对象:
map(function, iterable)
假设咱们有一个列表:
[1, 2, 3, 4, 5]
咱们但愿将列表中的每个数字进行平方,那么能够这么写代码:
x = [1, 2, 3, 4, 5] def square(num): return num*num print(list(map(square, x)))
Python中的函数是惰性的。若是咱们代码中不包含“list()”,函数将存储迭代的定义,而不是一个列表。咱们须要显式地告诉Python“将这个转换为一个列表”,以便咱们使用它。
如今写一个像“square(num)”这样的普通函数很好,可是它看起来不太对。咱们必须定义一个完整的函数才能在map中使用一次?咱们可使用lambda(匿名)函数在map中定义一个函数。
lambda表达式是一个单行函数。举个例子,这个lambda表达式对给定的一个数字求平方:
square = lambda x: x * x
运行程序:
>>> square(3) 9
告诉Python这是一个lambda函数,输入被称为x,冒号后面的内容就是你对输入的操做,它会自动返回结果。
如今咱们能够将上面的程序简化:
x = [1, 2, 3, 4, 5] print(list(map(lambda num: num * num, x)))
Reduce是一个函数,它把一个可迭代的东西变成一个东西。一般,您在一个列表上执行计算以将其缩减为一个数字。
Reduce是这样的:
reduce(function, list)
咱们能够(一般也会)使用lambda表达式做为函数。
列表的乘积是每个单独的数字相乘。要作到这一点,你能够:
product = 1x = [1, 2, 3, 4]for num in x: product = product * num
可是使用reduce你能够这样写:
from functools import reduce product = reduce((lambda x, y: x * y),[1, 2, 3, 4])
filter函数接受一个iterable并过滤掉在该iterable中不须要的全部东西。
filter一般接受一个函数和一个列表。它将函数应用于列表中的每一项,若是该函数返回True,则不执行任何操做。若是返回False,则从列表中删除该项目。
语法以下:
filter(function, list)
让咱们看看一个小例子,没有过滤器,咱们会写:
x = range(-5, 5) new_list = [] for num in x: if num < 0: new_list.append(num)
有了过滤器,这就变成:
x = range(-5, 5) all_less_than_zero = list(filter(lambda num: num < 0, x))
高阶函数能够将函数做为参数并返回函数。一个很是简单的例子以下:
def summation(nums): return sum(nums) def action(func, numbers): return func(numbers) print(action(summation, [1, 2, 3])) partial application
部分应用程序(也称为闭包)有点奇怪,可是很是酷。您能够调用一个函数而不提供它须要的全部参数。咱们来看一个例子。
咱们想要建立一个函数,它有两个参数,一个底数和一个指数,并返回底数的指数次方,就像这样:
def power(base, exponent): return base ** exponent
如今咱们想要一个专门的平方函数,用幂函数求出一个数的平方:
def square(base): return power(base, 2)
这是可行的,但若是咱们想要一个立方体函数呢?或者是函数的4次方?咱们能一直写下去吗?嗯,你能够。可是程序员很懒。
若是你一遍又一遍地重复一样的事情,这是一个信号,代表有一种更快的方法能够加快速度,让你再也不重复。咱们能够在这里使用部分应用程序。
让咱们看一个例子的平方函数使用部分应用程序:
from functools import partialsquare = partial(power, exponent=2)print(square(2))
这是否是很酷?咱们能够调用须要两个参数的函数,只需使用一个参数就能够告诉Python第二个参数是什么。
原文连接:
https://medium.com/hackernoon...
文源网络,仅供学习之用,侵删。在学习Python的道路上确定会碰见困难,别慌,我这里有一套学习资料,包含40+本电子书,800+个教学视频,涉及Python基础、爬虫、框架、数据分析、机器学习等,不怕你学不会!
https://shimo.im/docs/JWCghr8... 《Python学习资料》关注公众号【Python圈子】,优质文章每日送达。