python函数式编程

python 函数式编程

文章目录

  • python 函数式编程
    • 1. 什么是函数式编程
      • 1.1. 高阶函数
        • 1.1.1. map()和reduce()
        • 1.1.2. filter()函数
    • 2. 返回函数
    • 3. python函数式编程模块
      • 3.1. itertools模块
      • 3.2. operator模块
      • 3.3. functools模块
        • 3.3.1. partial对象

1. 什么是函数式编程

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

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

举例来说,现在有这样一个数学表达式:

(1+2)*3 -4

传统的过程式编程,可以写作:

a = 1+2
b = a*3
c = b-4

函数式编程就是把运算过程定义为不同的函数:

result = subtract(multiply(add(1,2),3)3)

函数式编程的一个特点就是,允许把函数本身作为参数传入另一个函数,还允许返回一个函数!

Python对函数式编程提供部分支持。由于Python允许使用变量,因此,Python不是纯函数式编程语言。

1.1. 高阶函数

高阶函数是指: 接受一个或者多个函数作为输入,输出一个函数.

python中的函数有以下特性:

  1. 变量可以指向函数:

    该概念是说可以把一个函数赋值给一个变量,例如:

    a = abs(-1) # 调用函数abs(-1)将计算结果赋值给a,那么a将是值为1的数字
    b = abs # 将abs写个函数本身赋值给变量b,即变量b指向abs这个函数
    

    将函数赋值给变量b后即可将b当作函数调用.

    >>>b(-1)
    >>>1
    
  2. 函数名也是变量

    函数名实际上就是指向函数的变量. 对于abs()这个函数,可以abs看作一个变量,它指向一个可以计算绝对值的函数.

  3. 传入函数

    既然变量可以指向函数,函数的参数能接收变量.

    一个简单的示例:

    f = abs
    def add(x,y,f):
        return f(x) + f(y)
    
    add(-1,1,f) #结果为2
    
1.1.1. map()和reduce()
  1. map()

    map()和reduce()函数是python的内建函数(builtins)

    map()函数接收两个参数,一个是函数,一个是Iterablemap将传入的函数依次作用到序列的每个元素,并把结果作为新的 Iterator返回。

    举例说明:

    def f(x):
        return x**2
    r = map(f,[1,2,3]) # r = [1,3,9]
    

    上述语句中的map函数将第二个参数中的列表元素逐个作为参数并调用函数f,将计算值组成一个新的list并返回.

  2. reduce()

    再看reduce的用法。reduce把一个函数作用在一个序列[x1, x2, x3, ...]上,这个函数必须接收两个参数,reduce把结果继续和序列的下一个元素做累积计算,其效果就是:

    reduce(f,[1,2,3,4]) = f(f(f(1,2)3)4)
    

    上面的代码已经很清楚的表现出了reduce函数的函数,它能很简洁的表达右边的过程.

    在python2中 map()和reduce()函数返回列表,在python3中返回的是一个可迭代对象.

1.1.2. filter()函数

filter顾名思义是一个过滤器. 它也接受一个函数和一个可迭代对象.
根据函数名也可以猜测到该函数是用于过滤,它顾虑掉序列中的不符合要求的元素.

所以和map一样filter传入的第一个参数是一个函数,它返回Ture/False,用来判断序列中的元素是否满足要求.下面的filter也一样.

举例:

#过滤掉大于10的数
def f(x):
    return f <= 10

a=list(filter(f,[1,11,20,8,9]) # a的值为[1,8,9]

2. 返回函数

  1. 函数作为返回值

    高阶函数除了可以接受函数作为参数外,还可以把函数作为结果值返回。

    举例说明:

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

    当我们调用lazy_sum()时,返回的并不是求和结果,而是求和函数:

    >>> f = lazy_sum(1, 3, 5, 7, 9)
    >>> f
    <function lazy_sum.<locals>.sum at 0x101c6ed90>
    

    调用函数f时,才真正计算求和的结果:

    >>> f()
    25
    
  2. 闭包

    闭包概念:在一个内部函数中,对外部作用域的变量进行引用,(并且一般外部函数的返回值为内部函数),那么内部函数就被认为是闭包。

    所以上述的lazy_sum()函数中的sum() 函数就是闭包.

    返回闭包时牢记一点:返回函数不要引用任何循环变量,或者后续会发生变化的变量。

3. python函数式编程模块

参考python官方文档

该模块提供了函数和类,以支持函数式编程风格和在可调用对象上的通用操作。

3.1. itertools模块

为高效循环而创建迭代器的函数

python文档

重要的函数:

无穷迭代器:

迭代器 实参 结果 示例
count() start, [step] start, start+step, start+2*step, … count(10) --> 10 11 12 13 14 …
cycle() p p0, p1, … plast, p0, p1, … cycle(‘ABCD’) --> A B C D A B C D …
repeat() elem [,n] elem, elem, elem, … 重复无限次或n次 repeat(10, 3) --> 10 10 10

根据最短输入序列长度停止的迭代器:

迭代器 实参 结果 示例
accumulate() p [,func] p0, p0+p1, p0+p1+p2, … accumulate([1,2,3,4,5]) --> 1 3 6 10 15
chain() p, q, … p0, p1, … plast, q0, q1, … chain(‘ABC’, ‘DEF’) --> A B C D E F
chain.from_iterable() iterable – 可迭代对象 p0, p1, … plast, q0, q1, … chain.from_iterable([‘ABC’, ‘DEF’]) --> A B C D E F
compress() data, selectors (d[0] if s[0]), (d[1] if s[1]), … compress(‘ABCDEF’, [1,0,1,0,1,1]) --> A C E F
dropwhile() pred, seq seq[n], seq[n+1], … 从pred首次真值测试失败开始 dropwhile(lambda x: x<5, [1,4,6,4,1]) --> 6 4 1
filterfalse() pred, seq seq中pred(x)为假值的元素,x是seq中的元素。 filterfalse(lambda x: x%2, range(10)) --> 0 2 4 6 8
groupby() iterable[, key] 根据key(v)值分组的迭代器
islice() seq, [start,] stop [, step] seq[start:stop:step]中的元素 islice(‘ABCDEFG’, 2, None) --> C D E F G
starmap() func, seq func(*seq[0]), func(*seq[1]), … starmap(pow, [(2,5), (3,2), (10,3)]) --> 32 9 1000
takewhile() pred, seq seq[0], seq[1], …, 直到pred真值测试失败 takewhile(lambda x: x<5, [1,4,6,4,1]) --> 1 4
tee() it, n it1, it2, … itn 将一个迭代器拆分为n个迭代器
zip_longest() p, q, … (p[0], q[0]), (p[1], q[1]), … zip_longest(‘ABCD’, ‘xy’, fillvalue=’-’) --> Ax By C- D-

排列组合迭代器:

迭代器 实参 结果
product() p, q, … [repeat=1] 笛卡尔积,相当于嵌套的for循环
permutations() p[, r] 长度r元组,所有可能的排列,无重复元素
combinations() p, r 长度r元组,有序,无重复元素
combinations_with_replacement() p, r 长度r元组,有序,元素可重复
product(‘ABCD’, repeat=2) AA AB AC AD BA BB BC BD CA CB CC CD DA DB DC DD
permutations(‘ABCD’, 2) AB AC AD BA BC BD CA CB CD DA DB DC
combinations(‘ABCD’, 2) AB AC AD BC BD CD
combinations_with_replacement(‘ABCD’, 2) AA AB AC AD BB BC BD CC CD DD

3.2. operator模块

operator 模块提供了一套与Python的内置运算符对应的高效率函数。例如,operator.add(x, y) 与表达式 x+y 相同。 许多函数名与特殊方法名相同,只是没有双下划线。为了向后兼容性,也保留了许多包含双下划线的函数。为了表述清楚,建议使用没有双下划线的函数。

函数包含的种类有:对象的比较运算、逻辑运算、数学运算以及序列运算。

对象比较函数适用于所有的对象,函数名根据它们对应的比较运算符命名。

官方文档

运算 语法 函数
加法 a + b add(a, b)
字符串拼接 seq1 + seq2 concat(seq1, seq2)
包含测试 obj in seq contains(seq, obj)
除法 a / b truediv(a, b)
除法 a // b floordiv(a, b)
按位与 a & b and_(a, b)
按位异或 a ^ b xor(a, b)
按位取反 ~ a invert(a)
按位或 a | b or_(a, b)
取幂 a ** b pow(a, b)
一致 a is b is_(a, b)
一致 a is not b is_not(a, b)
索引赋值 obj[k] = v setitem(obj, k, v)
索引删除 del obj[k] delitem(obj, k)
索引取值 obj[k] getitem(obj, k)
左移 a << b lshift(a, b)
取模 a % b mod(a, b)
乘法 a * b mul(a, b)
矩阵乘法 a @ b matmul(a, b)
否定(算术) - a neg(a)
否定(逻辑) not a not_(a)
正数 + a pos(a)
右移 a >> b rshift(a, b)
切片赋值 seq[i:j] = values setitem(seq, slice(i, j), values)
切片删除 del seq[i:j] delitem(seq, slice(i, j))
切片取值 seq[i:j] getitem(seq, slice(i, j))
字符串格式化 s % obj mod(s, obj)
减法 a - b sub(a, b)
真值测试 obj truth(obj)
比较 a < b lt(a, b)
比较 a <= b le(a, b)
相等 a == b eq(a, b)
不等 a != b ne(a, b)
比较 a >= b ge(a, b)
比较 a > b gt(a, b)

3.3. functools模块

函数 功能
functools.cmp_to_key(func) 将cmp函数转换为key函数,为了兼容py2
@functools.lru_cache(maxsize=128, typed=False) 一个为函数提供缓存功能的装饰器,缓存 maxsize 组传入参数,在下次以相同参数调用时直接返回上一次的结果。用以节约高开销或I/O函数的调用时间。有了它就可以不使用dp啦。
@functools.total_ordering 它是针对某个类如果定义了lt、le、gt、ge这些方法中的至少一个,使用该装饰器,则会自动的把其他几个比较函数也实现在该类中。此类必须包含以下方法之一:lt() 、le()、gt() 或 ge()。另外,此类必须支持 eq() 方法。
functools.partial(func, *args, **keywords) 该函数的目的是为了减少参数func函数的参数。返回一个于func功能一样的函数,但是预先填写了参数(partial函数后两个参数传入的。)
class functools.partialmethod(func, *args, **keywords) 返回一个新的partialmethod描述符,该描述符的行为类似于partial,只是它被设计为用作方法定义而不是可直接调用的。
functools.reduce(function, iterable[, initializer]) reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) = ((((1+2)+3)+4)+5).
3.3.1. partial对象

partial对象是由partial()函数创建的可调用对象. 它有三个只读属性:

functools.partial(func, *args, **keywords)

  • parial.dunc

    一个可调用对象或者函数. 调用partial对象将会带着传入的参数转发给func.
    也就是说调用partial实际上是调用func的功能只是将partial的参数传递给func

  • partial.args

    调用partial时传入的参数,它将会被传递给func

  • partial.keywords

    调用partial时传入的关键字参数. 它将被传入func

参考:https://www.liaoxuefeng.com/wiki/1016959663602400/1017328525009056
参考:https://docs.python.org/zh-cn/3.7/library/functional.html

你可能感兴趣的:(python)