Python基础:09函数式编程
Python支持一些函数式编程的特性。比如lambda、 map()、reduce()、filter()函数。
一:匿名函数与lambda
Python可以用lambda 关键字创造匿名函数。匿名函数不需要以标准的方式来声明(使用def 语句)。作为函数,它们也能有参数。
一个完整的lambda“语句”代表了一个表达式,这个表达式的定义体必须和声明放在同一行。匿名函数的语法如下:
lambda [arg1[, arg2, ... argN]]: expression
参数是可选的,lambda 生成一个可以像其他函数一样使用的函数对象。
比如下面的简单函数:
def true(): return True
对于该函数,可以使用lambda表达式生成等价的函数对象:
>>> lambda :True
<function <lambda> at f09ba0>
在上面的例子中,只是简单地用lambda创建了一个函数(对象),但是该函数对象创建完之后就被垃圾回收了。
为了保留住这个对象,将它保存到一个变量中,以后可以随时调用:
>>> true = lambda :True
>>> true()
True
下面是更多的例子:
def add(x, y): return x + y 等价于 lambda x, y: x + y
def usuallyAdd2(x, y=2): return x+y 等价于 lambda x, y=2: x+y
def showAllAsTuple(*z): return z等价于lambda *z: z
>>> a = lambda x, y=2: x + y
>>> a(3)
5 >>> a(3,5)
8 >>> a(0)
2 >>> a(0,9)
9
>>>
>>> b = lambda *z: z
>>> b(23, 'zyx')
(23, 'zyx') >>> b(42)
(42,)
二:filter()、map()、reduce()
这些函数提供了在python 中可以找到的函数式编程的特征。lambda 表达式可以很好的和这些函数相结合,因为这些函数都带了一个可执行的函数对象的参数。lambda 表达式提供了迅速创造这个参数的机制。
a:filter(function, iterable)
给定一个对象的序列和一个“过滤”函数,每个序列元素都通过这个过滤器进行筛选,保留函数返回为真的的对象。filter 函数为已知的序列的每个元素调用给定布尔函数function。将经过function处理返回True值的元素添加到一个列表中。返回的对象是一个从原始队列中“过滤后”的列表。
注意:如果iterable是一个字符串或者元组的话,则结果也是同样的类型,否则,结果为一个列表。如果function为None的话,则该函数表现为一个身份函数,也就是该函数会返回,iterable中所有值为True的元素组成的列表。
如果用纯python 编写filter(),它或许就像这样:
def filter(bool_func, seq):
filtered_seq= []
for eachItem in seq:
if bool_func(eachItem):
filtered_seq.append(eachItem) return filtered_seq
例子如下:
>>> alist = [1,2,3,0,4,5]
>>> filter(None, alist)
[1, 2, 3, 4, 5] >>> filter(lambda x: True,'abcdefg')
'abcdefg' >>> filter(lambda x: True,(1,2,3,4,5))
(1, 2, 3, 4, 5)
注意,如果function不是None的话,则filter(function,iterable)等价于:[item for item in iterable if function(item)]。如果function为None的话,则它等价于[itemfor item in iterable if item]。比如求一个随机列表中所有奇数的方法:
allNums = []
for eachNum in range(9):
allNums.append(randint(1,99)) print filter(lambda n: n%2, allNums)
等价于:
allNums = []
for eachNum in range(9):
allNums.append(randint(1,99))
print [n for n in allNums if n%2]
b:map(function, iterable, ...)
将function应用到iterable中的每个元素上,并返回一个由返回值组成的列表。如果给出了多个iterable参数,则function必须具有相同数目的参数,并且该function会并行的迭代所有iterable中的元素。如果其中一个iterable比较短,则假设用None将其扩展。
如果function为None,则如果给出了多个iterable,那map返回一个元素为元组的列表,其中的元组包含所有iterable的相应元素。
该函数的结果只能是列表。
如果要用python 编写一个简单的只有一个iterable的map(),代码如下:
def map(func, seq):
mapped_seq= []
for eachItem in seq:
mapped_seq.append(func(eachItem))
return mapped_seq
例子如下:
>>> map((lambda x: x+2), [0, 1, 2, 3, 4, 5])
[2, 3, 4, 5, 6, 7] >>> map(None, (1,2,3,4),'abc')
[(1, 'a'), (2, 'b'), (3, 'c'), (4, None)] >>> map(lambda x: x**2, range(6))
[0, 1, 4, 9, 16, 25] >>> map(lambda x, y: x + y, [1,3,5], [2,4,6])
[3, 7, 11] >>> map(lambda x, y: (x+y, x-y), [1,3,5],[2,4,6])
[(3, -1), (7, -1), (11, -1)] >>> map(None, [1,3,5], [2,4,6])
[(1, 2), (3, 4), (5, 6)]
c:reduce(function, iterable[, initializer])
function是有两个参数的函数,它会持续的对iterable中,从左到右的每个元素进行处理,从而会将iterable中所有元素reduce为一个值。比如reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]),将会计算((((1+2)+3)+4)+5)。左参数x是累计计算的结果,右参数y是iterable中的下一个元素。如果给定initializer参数值的话,则它会是第一个左参数,iterable中的第一个元素是第一个右参数。如果initializer没有给定值,则第一个左参数为iterable[0],第一个右参数为iterable[1]。
reduce的类Python代码实现如下:
def reduce(function, iterable, initializer=None):
it = iter(iterable)
if initializeris None:
try:
initializer= next(it)
except StopIteration:
raiseTypeError('reduce() of empty sequence with no initial value') accum_value =initializer
for x in it:
accum_value= function(accum_value, x) return accum_value
例子如下;
>>> print 'the total is:', reduce((lambda x,y:x+y), range(5))
the total is: 10
三:偏函数
偏函数类似于默认参数,可以降低函数调用的难度。举例如下:
int()函数可以把字符串转换为整数,当仅传入字符串时,int()函数默认按十进制转换:
>>> int('')
12345
但int()函数还提供额外的base参数,默认值为10。如果传入base参数,就可以做N进制的转换:
>>> int('', base=8)
5349 >>> int('', 16)
74565
假设要转换大量的二进制字符串,每次都传入int(x, base=2)非常麻烦,于是,我们想到,可以定义一个int2()的函数,默认把base=2传进去:
def int2(x, base=2):
return int(x, base)
这样,我们转换二进制就非常方便了:
>>> int2('')
64 >>> int2('')
85
functools.partial就是帮助我们创建一个偏函数的,不需要我们自己定义int2(),可以直接使用下面的代码创建一个新的函数int2:
>>> import functools >>> int2 = functools.partial(int, base=2)
>>> int2('')
64 >>> int2('')
85
所以,简单总结functools.partial的作用就是,把一个函数的某些参数给固定住(也就是设置默认值),返回一个新的函数,调用这个新函数会更简单。
注意到上面的新的int2函数,仅仅是把base参数重新设定默认值为2,但也可以在函数调用时传入其他值:
>>> int2('', base=10)
1000000
最后,创建偏函数时,实际上可以接收函数对象、*args和**kw这3个参数,当传入:int2 = functools.partial(int, base=2)实际上固定了int()函数的关键字参数base,也就是:
int2('10010')
相当于:
kw = { base: 2 }
int('10010', **kw)
当传入:
max2 = functools.partial(max, 10)
实际上会把10作为*args的一部分自动加到左边,也就是:
max2(5, 6, 7)
相当于:
args = (10, 5, 6, 7)
max(*args)
结果为10。
参考:http://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000/001386819893624a7edc0e3e3df4d5d852a352b037c93ec000
Python基础:09函数式编程的更多相关文章
- Python基础:函数式编程
一.概述 Python是一门多范式的编程语言,它同时支持过程式.面向对象和函数式的编程范式.因此,在Python中提供了很多符合 函数式编程 风格的特性和工具. 以下是对 Python中的函数式编程 ...
- python基础之函数式编程、匿名函数、内置函数
一 函数式编程 不修改外部状态. 模仿数学里得函数进行编程. 用函数编程写出得代码相当精简. 可读性比较差. 例子: y=2*x+1 x=1 def test(x): return 2*x+1 tes ...
- python基础之函数式编程
一.定义: 函数作为参数作用:将核心逻辑传入方法体,使该方法的适用性更广,体现了面向对象的开闭原则: 函数作为返回值作用:逻辑连续,当内部函数被调用时,不脱离当前的逻辑. 二.高阶函数: 1.定义:将 ...
- Python进阶:函数式编程实例(附代码)
Python进阶:函数式编程实例(附代码) 上篇文章"几个小例子告诉你, 一行Python代码能干哪些事 -- 知乎专栏"中用到了一些列表解析.生成器.map.filter.lam ...
- 可爱的 Python : Python中的函数式编程,第三部分
英文原文:Charming Python: Functional programming in Python, Part 3,翻译:开源中国 摘要: 作者David Mertz在其文章<可爱的 ...
- Python Decorator 和函数式编程
看到一篇翻译不错的文章,原文链接: Python Decorator 和函数式编程
- Python进阶之函数式编程(把函数作为参数)
什么是函数式编程? 什么是函数式编程? 函数:function 函数式:functional,一种编程范式 函数式编程是一种抽象计算的编程模式 函数≠函数式,比如:计算≠计算机 在计算机当中,计算机硬 ...
- Python 基础之socket编程(二)
Python 基础之socket编程(二) 昨天只是对socket编程做了简单的介绍,只是把socket通信的框架搭建起来,要对其中的功能进行进一步的扩充,就来看看今天的料哈! 一.基于tcp的套接字 ...
- python基础之socket编程 (转自林海峰老师)
python基础之socket编程 阅读目录 一 客户端/服务器架构 二 osi七层 三 socket层 四 socket是什么 五 套接字发展史及分类 六 套接字工作流程 七 基于TCP的套接字 ...
随机推荐
- MAC中怎么安装python
转自:https://blog.csdn.net/hou_manager/article/details/79555809 一.Python 介绍 Python介绍 Python3在2008年12月3 ...
- CodeChef--SEPT14小结
这套题目只做了几个相对简单的.其他的做起来比较吃力. A 找下规律 /***************************************************************** ...
- angular4 自定义表单组件
自定义表单组件分为单值组件和多值组件. 单值组件:input/select/radio/textarea 多值组件:checkbox/tree组件 条件: 1.必须实现ControlValueAcce ...
- ModelAndView返回mav时,报404
报404的可能性太多了 简单来看,404后边有信息,说明请已经分配到了控制器 经过调试发现,mav已经分配到了页面 原因,modelandview的包导入错误,正确的包是 import org.spr ...
- 1.1Jupyter notbook 的使用
目录 目录 (一)安装Jupyter notebook 1.在控制台输入: 2.注意: 3.安装的过程: (二)启动Jupyter notebook (三)文件管理 (四)基本概念与操作 1.什么是C ...
- go语言:获取字符串长度
go语言字符串底层由字节数组实现,使用UTF-8编码,初始化以后不能被修改 获取字符串长度 一.当字符串中所有字符都是单字节字符时,使用 len 函数获取字符串的长度 package main imp ...
- 洛谷P1084 [NOIP2012提高组Day2T3]疫情控制
P1084 疫情控制 题目描述 H 国有 n 个城市,这 n 个城市用 n-1 条双向道路相互连通构成一棵树,1 号城市是首都,也是树中的根节点. H 国的首都爆发了一种危害性极高的传染病.当局为了控 ...
- 各大ACM OJ网址
做快乐的程序员 以你的条件,你不必追求优秀,但你可以做到良好. 各大OJ网址 ACM OJ Collection(排名不分先后): 中国:(China) 华东地区: 浙江: 杭州电子科技大学(HDU) ...
- Linux操作系统各版本ISO镜像下载(包括oracle linux\redhat\centos\u
Linux操作系统各版本ISO镜像下载(包括oracle linux\redhat\centos\ubuntu\debian等) 1.Oracle Linux(下载地址) (1)OracleLinux ...
- loadrunner分析之-网页、网络、资源分析
在Web Page Diagnostics(网页分析)中当在场景中打开Diagnostics菜单下的Web Page Diagnostics功能,就能得到网页分析组图.通过这个图,可以对事务的组成进行 ...