python函数式编程

python 函数式编程

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()pp0, 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, seqseq[n], seq[n+1], … 从pred首次真值测试失败开始dropwhile(lambda x: x<5, [1,4,6,4,1]) --> 6 4 1
filterfalse()pred, seqseq中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, seqfunc(*seq[0]), func(*seq[1]), …starmap(pow, [(2,5), (3,2), (10,3)]) --> 32 9 1000
takewhile()pred, seqseq[0], seq[1], …, 直到pred真值测试失败takewhile(lambda x: x<5, [1,4,6,4,1]) --> 1 4
tee()it, nit1, 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 + badd(a, b)
字符串拼接seq1 + seq2concat(seq1, seq2)
包含测试obj in seqcontains(seq, obj)
除法a / btruediv(a, b)
除法a // bfloordiv(a, b)
按位与a & band_(a, b)
按位异或a ^ bxor(a, b)
按位取反~ ainvert(a)
按位或a | bor_(a, b)
取幂a ** bpow(a, b)
一致a is bis_(a, b)
一致a is not bis_not(a, b)
索引赋值obj[k] = vsetitem(obj, k, v)
索引删除del obj[k]delitem(obj, k)
索引取值obj[k]getitem(obj, k)
左移a << blshift(a, b)
取模a % bmod(a, b)
乘法a * bmul(a, b)
矩阵乘法a @ bmatmul(a, b)
否定(算术)- aneg(a)
否定(逻辑)not anot_(a)
正数+ apos(a)
右移a >> brshift(a, b)
切片赋值seq[i:j] = valuessetitem(seq, slice(i, j), values)
切片删除del seq[i:j]delitem(seq, slice(i, j))
切片取值seq[i:j]getitem(seq, slice(i, j))
字符串格式化s % objmod(s, obj)
减法a - bsub(a, b)
真值测试objtruth(obj)
比较a < blt(a, b)
比较a <= ble(a, b)
相等a == beq(a, b)
不等a != bne(a, b)
比较a >= bge(a, b)
比较a > bgt(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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值