Python进阶:函数式编程实例(附代码)

上篇文章“几个小例子告诉你, 一行Python代码能干哪些事 -- 知乎专栏”中用到了一些列表解析、生成器、map、filter、lambda、zip等表达形式,这就涉及到了Python中关于函数式编程(functional programming)的语法、函数等。这里我们就根据一些实例,聊聊Python中的函数式编程。

先附上维基百科中关于函数式编程的解释:

函数式编程,或称函数程序设计,又称泛函编程,是一种编程范型,它将电脑运算视为数学上的函数计算,并且避免使用程序状态以及易变对象。函数编程语言最重要的基础是λ演算。而且λ演算的函数可以接受函数当作输入(引数)和输出(传出值)。

比起命令式编程,函数式编程更强调程序执行的结果而非执行的过程,倡导利用简单的执行单元让计算结果不断渐进,逐层推导复杂的运算,而不是设计一个复杂的执行过程。

关于函数式编程的好处、原则等等,我们就不聊了,大家可以自行谷歌。

Python作为一门脚本语言,也具有一些函数式编程的思想,主要体现在下面几个方面:

  • Python的一些语法,比如lambda、列表解析、字典解析、生成器、iter等
  • Python的一些内置函数,包括map、reduce、filter、all、any、enumerate、zip等
  • Python的一些内置模块,比如 itertools、functools 和 operator模块等
  • Python的一些第三方库,比如fn.py, toolz等

这里我们就根据这四个方面,分别聊一聊各自的语法、实例等。

Python函数式编程之语法篇

(1)列表解析,将range(5)的每个元素进行平方:

a_list = [item**2 for item in range(5)]
print(a_list) # [0, 1, 4, 9, 16]

(2)字典解析,将range(5)的每个元素进行平方并作为value,key为一个指示:

a_dict = {"%d^2" % item: item**2 for item in range(5)}
print(a_dict) # {'3^2': 9, '2^2': 4, '1^2': 1, '0^2': 0, '4^2': 16}

(3)生成器:和列表解析比较类似,区别在于它的结果是generator object,不能直接打印,但可以进行迭代(使用next函数、放入for循环等)。

a_generator = (item**2 for item in range(5))
print(a_generator) # <generator object <genexpr> at 0x10e366570>
print(next(a_generator)) # 0
print(next(a_generator)) # 1

(4)iter函数和next函数:一个list类型不能使用next函数,需将其转化为iterator类型。

a_list_generator = iter(a_list)
print(next(a_list_generator)) # 0
print(type(a_list), type(a_list_generator)) # <class 'list'> <class 'list_iterator'>

(5)lambda表达式,即定义一些比较简单的匿名函数,lambda表达式和map、reduce、filter等函数混合使用威力巨大。例如求x的y次方:

a_func = lambda x, y: x**y
print(a_func(2, 3)) # 8

Python函数式编程之内置函数篇

这里没有将iter和next归到这里,只是个人喜好而已,大家不用在意这些细节。

(1)map函数:将一个函数应用于一个或多个可迭代对象,返回一个map object。这里的函数可以为内置函数、operator模块中的函数或者一个lambda函数等:

print(map(abs, range(-4, 5)))    # <map object at 0x1097bd6d8>
print(list(map(abs, range(-4, 5)))) # [4, 3, 2, 1, 0, 1, 2, 3, 4]
print(list(map(lambda x: x**2, range(5)))) # [0, 1, 4, 9, 16]
print(list(map(lambda x, y: x**y, range(1, 5), range(1, 5)))) # [1, 4, 27, 256]

(2)reduce函数:这个函数并不能直接调用,而是需要通过functools库进行引入。该函数的作用是将一个可迭代对象中的元素进行reduce(累加等),最后一个参数可选,为初始值。

print(reduce(lambda x, y: x+y, range(10)))    # 45
print(reduce(lambda x, y: x+y, range(10), 100)) # 145
print(reduce(lambda x, y: x+y, [[1, 2], [3, 4]], [0])) # [0, 1, 2, 3, 4]

(3)filter函数:按照字面意思理解即可,即过滤一个可迭代对象,保留为True的元素。注意第二个例子,只过滤掉0,因为即使是负数也会被判定为True。

print(filter(None, range(-4, 5)))    # <filter object at 0x10c096710>
print(list(filter(None, range(-4, 5)))) # [-4, -3, -2, -1, 1, 2, 3, 4]
print(list(filter(lambda x: x > 0, range(-4, 5)))) # [1, 2, 3, 4]

(4)all、any函数:比较简单,还是可以按照字面意思理解,即判定一个可迭代对象是否全为True或者有为True的。

print(all([0, 1, 2]))    # False
print(any([0, 1, 2])) # True

(5)enumerate函数,如果你想迭代一个列表或者元组,又想知道当前迭代元素的index值,那么enumerate就能满足你的需求:

for index, item in enumerate(range(5)):
print("%d: %d" % (index, item)) # 0: 0 \n 1: 1 \n 2: 2 ......

(6)zip函数,映射两个或多个可迭代对象,组成新的可迭代对象,直接看实例:

for a, b in zip([1, 2, 3], ["a", "b", "c"]):
print(a, b) # 1 a \n 2 b \n 3 c
a_dict = dict(zip([1, 2, 3], ["a", "b", "c"]))
print(a_dict) # {1: 'a', 2: 'b', 3: 'c'}

Python函数式编程之内置模块篇

这里主要涉及内置模块itertools、functools和operator等。这几个内置模块可配合上边的map、reduce等函数一起使用。由于涉及到的内容较多,这里只做简单介绍。有什么不明白或者不清楚的地方,可以读一下Python的官方文档:Functional Programming Modules

(1)itertools模块:包含创建有效迭代器的函数,可以用各种方式对数据进行循环操作,该模块的所有函数返回的迭代器都可以与for循环语句以及其他包含迭代器的函数联合使用。主要包含三类函数:

  • 无限迭代器,比如itertools.count(10, 2)将无限产生从10开始,step为2的数,这里需要用break手动停止。

  • 作用于序列上的一些迭代器,比如itertools.chain(a_list, b_list)将两个列表连起来。

  • 组合生成器,比如排列功能、组合功能等。

(2)functools模块:定义一些高阶函数,用于“act”或者“return”其他函数。前边已经介绍过其中的一个函数reduce了。这里再介绍一个平时常用的partial函数,其他函数大家可以参考其官方文档。

print(int("10010", base=2))    # 18
int_base_2 = partial(int, base=2) # partial可以给函数添加或更改默认参数
print(int_base_2("10010")) # 18

(3)operator模块:提供了一个与Python固有操作相对应的集合。例如operator.add(x, y)等价于表达式x+y。该模块中函数的名字就是类的方法名。这里可以结合map、reduce等使用:

print(reduce(lambda x, y: x+y, range(10)))    # 45
print(reduce(add, range(10))) # 45

Python函数式编程之第三方库

第三方库包括fn.py, toolz等,fn.py地址:GitHub - kachayev/fn.py: Functional programming in Python,toolz地址:pytoolz/toolz: A functional standard library for Python。两个第三方库的很多功能都和Python内置的语法、函数类似,这里就不一一解释了。这里就举一个fn.py的例子,其他的大家可以去参考他的代码或者文档:

from fn import _
add_func_1 = (_ + 2)
print(add_func_1(1)) # 3
add_func_2 = (_ + _ * _)
print(add_func_2(1, 2, 3)) # 7

以上大概就是Python函数式编程的基本语法、函数、思想等,有什么问题可以在评论中指出,大家一起讨论,一起进步。对了,Python中的装饰器应该也算是函数式编程的一种用法,有时间专门写一篇关于Python装饰器的文章。

按照惯例,文章中出现的所有代码,均已上传到Github:GitHub - xianhu/LearnPython: 以撸代码的形式学习Python

作者GitHub主页:撸代码,学知识 - GitHub

Python进阶:函数式编程实例(附代码)的更多相关文章

  1. Python进阶 函数式编程和面向对象编程等

    函数式编程 函数:function 函数式:functional,一种编程范式.函数式编程是一种抽象计算机的编程模式. 函数!= 函数式(如计算!=计算机) 如下是不同语言的抽象 层次不同 高阶函数: ...

  2. 慕课网python进阶函数式编程学习记录

    函数 不等于 函数式 函数: function 函数式: functional,一种编程范式 就好比计算机 不等于 计算 c语言: 函数 python :函数式(计算) 函数式编程特点: 把计算视为函 ...

  3. 可爱的 Python : Python中函数式编程,第一部分

    英文原文:Charming Python: Functional programming in Python, Part 1 摘要:虽然人们总把Python当作过程化的,面向对象的语言,但是他实际上包 ...

  4. python基础-函数式编程

    python基础-函数式编程  高阶函数:map , reduce ,filter,sorted 匿名函数:  lambda  1.1函数式编程 面向过程编程:我们通过把大段代码拆成函数,通过一层一层 ...

  5. Python的函数式编程: map, reduce, sorted, filter, lambda

    Python的函数式编程 摘录: Python对函数式编程提供部分支持.由于Python允许使用变量,因此,Python不是纯函数式编程语言. 函数是Python内建支持的一种封装,我们通过把大段代码 ...

  6. python 10函数式编程

                                                                               函数式编程 函数是Python内建支持的一种封装, ...

  7. 可爱的 Python : Python中函数式编程,第二部分

    英文原文:Charming Python: Functional programming in Python, Part 2,翻译:开源中国 摘要:  本专栏继续让David对Python中的函数式编 ...

  8. python专题-函数式编程

    函数式编程是使用一系列函数去解决问题,按照一般编程思维,面对问题时我们的思考方式是"怎么干",而函数函数式编程的思考方式是我要"干什么". 至于函数式编程的特点 ...

  9. 【python】函数式编程

    No1: 函数式编程:即函数可以作为参数传递,也可以作为返回值  No2: map()函数接收两个参数,一个是函数,一个是Iterable,map将传入的函数依次作用到序列的每个元素,并把结果作为新的 ...

随机推荐

  1. python【第六篇】面向对象编程

    面向对象编程 一.编程范式:编程的方法论.程序员编程的“套路”及“特点”特点总结,抽象成方法.规范. 二.面向对象编程介绍: 1.描述 世界万物,皆可分类:世间万物,皆为对象:只要是对象,就肯定属于某 ...

  2. centos 下vmware 下添加硬盘到root

    ### #vmware 里找到硬盘拖大点...,如果不想从启动么,添加个新 #的也行.不过那个是另外的方法了 ###   #### ##找下硬盘添加在哪里 #### fdisk -l    //创建分 ...

  3. Oracle数据库基础知识_字符串操作相关2

    6.LPAD,RPAD 作用:左/右边的字符串填充一些特定的字符语法: LPAD(string , n, [pad_String])          string:可是字符或者参数          ...

  4. Python模块解析之SocketServer(三)——模块思想

            SocketServer 体系 由两个部分构成 BaseServer 和 BaseRequestHandler.思想很简单 BaseServer接受请求,将请求交给BaseReques ...

  5. Solr4.8.0源码分析(26)之Recovery失败造成的宕机原因分析

    最近在公司做SolrCloud的容灾测试,刚好碰到了一个比较蛋疼的问题,跟SolrCloud的Recovery和leader选举有关,正好拿出来分析下. 现象是这样的:比如我有一台3个shard的So ...

  6. Keil c51现No Browse information available

    keil c51 不能使用:Go to Definition of....的解决方法 最近使用keil c51 开发usb固件,当向vc一样使用Go to Definition of....时,出现警 ...

  7. Gridview BottomPagerRow添加自定义控件

    pager.ascx public partial class pager : System.Web.UI.UserControl{ } .aspx protected pager ctl; prot ...

  8. [转]Aggregate tasks i Sharepoint 2013

    from http://sharepoint247.com/mysite/aggregate-tasks-i-sharepoint-2013/ Aggregate tasks i Sharepoint ...

  9. 又是干货,这个春节感觉吃饱了。各方面---RHCS集群理论

    什么是集群?    集群是一组(>2)相互独立的,通过高速网络互联的计算机组成的集合.群集一般可以分为科学集群,负载均衡集群,高可用性集群三大类.    科学集群是并行计算的基础.它对外就好象一 ...

  10. bzoj1978

    朴素的算法是O(n2logn)观察这个算法,似乎很难在进行优化我们就要换一种思路考虑到一个数的约数总不是很多,穷举约数也是可以在O(sqrt(x))的时间内完成的并且注意到,能否继续往下选数,只在于最 ...