Python函数式编程

2020-11-21  本文已影响0人  yufeiyang1995

工作的项目主要是以Python进行开发的,经常会看到项目代码中的lambda表达式还有一些把函数作为参数或放在集合中的用法。之前只是浅显的知道是函数式编程,这里好好研究一下。下面从以下几个部分进行学习:

什么是函数式编程?

简单说,"函数式编程"是一种"编程范式"(programming paradigm),也就是如何编写程序的方法论。

它属于"结构化编程"的一种,主要思想是把运算过程尽量写成一系列嵌套的函数调用。

函数式编程关心类型(代数结构)之间的关系,是一种抽象程度很高的编程范式;
而命令式编程则关心解决问题的步骤。

函数式编程特点

函数式编程具有五个鲜明的特点。

  1. 函数是"第一等公民"

所谓"第一等公民"(first class),指的是函数与其他数据类型一样,处于平等地位,可以赋值给其他变量,也可以作为参数,传入另一个函数,或者作为别的函数的返回值。

举例来说,下面代码中的print变量就是一个函数,可以作为另一个函数的参数。

var print = function(i){ console.log(i);};
[1,2,3].forEach(print);
  1. 只用"表达式",不用"语句"

"表达式"(expression)是一个单纯的运算过程,总是有返回值;"语句"(statement)是执行某种操作,没有返回值。函数式编程要求,只使用表达式,不使用语句。也就是说,每一步都是单纯的运算,而且都有返回值。

原因是函数式编程的开发动机,一开始就是为了处理运算(computation),不考虑系统的读写(I/O)。"语句"属于对系统的读写操作,所以就被排斥在外。

3. 没有"副作用"

所谓"副作用"(side effect),指的是函数内部与外部互动(最典型的情况,就是修改全局变量的值),产生运算以外的其他结果。

函数式编程强调没有"副作用",意味着函数要保持独立,所有功能就是返回一个新的值,没有其他行为,尤其是不得修改外部变量的值。

  1. 不修改状态

上一点已经提到,函数式编程只是返回新的值,不修改系统变量。因此,不修改变量,也是它的一个重要特点。

5. 引用透明

引用透明(Referential transparency),指的是函数的运行不依赖于外部变量或"状态",只依赖于输入的参数,任何时候只要参数相同,引用函数所得到的返回值总是相同的。

函数式编程的作用

  1. 代码简洁,开发快速
  2. 接近自然语言,易于理解
  3. 更方便的代码管理
  4. 易于"并发编程"

Python中的函数式编程

在Python中,函数式编程主要通过使用:

  1. 高阶函数
  2. 返回函数
  3. lambda函数
  4. 装饰器
  5. 偏函数

高阶函数

一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数。

例如,

def add(x, y, f):
    return f(x) + f(y)

print(add(-5, 6, abs))

Python中还内置了三种常用的高阶函数:

>>> def f(x):
...     return x * x
...
>>> r = map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> list(r)
[1, 4, 9, 16, 25, 36, 49, 64, 81]

reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)

>>> from functools import reduce
>>> def add(x, y):
...     return x + y
...
>>> reduce(add, [1, 3, 5, 7, 9])
25
def is_odd(n):
    return n % 2 == 1

list(filter(is_odd, [1, 2, 4, 5, 6, 9, 10, 15]))
# 结果: [1, 5, 9, 15]
>>> sorted([36, 5, -12, 9, -21], key=abs)
[5, 9, -12, -21, 36]

返回函数

返回求和函数

def lazy_sum(*args):
    def sum():
        ax = 0
        for n in args:
            ax = ax + n
        return ax
    return sum

闭包:一个函数定义中引用了函数外定义的变量,并且该函数可以在其定义环境外被执行

def outer_func():
    loc_list = []
    def inner_func(name):
        loc_list.append(len(loc_list) + 1)
        print '%s loc_list = %s' %(name, loc_list)
    return inner_func

在这个例子中我们至少可以对闭包中引用的自由变量有如下的认识:

lambda函数

  1. 一个语法

在Python中,lambda的语法是唯一的。其形式如下:
lambda argument_list: expression

其中,lambda是Python预留的关键字,argument_list和expression由用户自定义。这里的argument_list是参数列表,expression是一个关于参数的表达式。
这里的lambda argument_list: expression表示的是一个函数。这个函数叫做lambda函数。

  1. 三个特性

lambda函数有如下特性:

下面是一些lambda函数示例:

  1. 四个用法

由于lambda语法是固定的,其本质上只有一种用法,那就是定义一个lambda函数。在实际中,根据这个lambda函数应用场景的不同,可以将lambda函数的用法扩展为以下几种:

例如:

dim_met_list = sorted(dim_met_list, key=lambda d: (int(d["map_type"]), 
int(d["dim_met_order"])))
list(map(lambda x: DATA_SET_PREFIX + x, DATA_SET_FIELD_SET))
  1. 一个争议

装饰器

一种常用的返回函数,特殊的闭包

偏函数

>>> int('12345')
12345
>>> int('12345', base=8)
5349
>>> import functools
>>> int2 = functools.partial(int, base=2)
>>> int2('1000000')
64
>>> int2('1010101')
85

总结

个人理解在一些数值计算和装饰器场景可以使用函数式编程使代码更简单,但是复杂的业务场景不建议使用函数式编程,会使代码难以理解,增加维护成本,降低开发效率。

参考文章:
https://www.liaoxuefeng.com/wiki/1016959663602400/1017328525009056

http://www.ruanyifeng.com/blog/2012/04/functional_programming.html

https://zhuanlan.zhihu.com/p/67978661

上一篇下一篇

猜你喜欢

热点阅读