文档章节

Python里的匿名函数(lambda)与apply(),filter() ,map(),reduce(),以及函数的可变长参数

lionets
 lionets
发布于 2013/12/24 09:33
字数 2014
阅读 7926
收藏 12
点赞 1
评论 0

lambda:

提到 Lambda演算,更多时候是与函数式编程纠缠在一起的。这种设计思想讲究抛弃变量和状态,使用纯函数的递归系统来构建程序(个人理解)。虽然函数式编程与 Python 的面向对象背道而驰,但并不妨害 Python 借鉴其中某些有价值的内容。即是说,并不能因为 lambda 的存在就认为 Python 是一门函数式编程语言,它只是因为在某些细节上显得更有效率而被引入的。比如 Python 里用 lambda 来定义匿名函数,并与标题中提到的 apply() 等内建函数一起构建一些程序结构。

匿名函数与标准方式声明的函数区别在于,不需要使用 def 语句,也不需要一个名字来引用它。使用 lambda 语句可以直接得到一个函数对象,它的语法是:

lambda [arg1[,arg2…]]: expression

参数可有可无,冒号后面是一个表达式,函数的作用就是返回这个表达式的值。在 def 语句下等同于:

def func([arg1[,arg2…]]):return expression

可以看到 lambda 函数没有中间状态,也不适合构建过于复杂的函数,因为它的函数体只有一个表达式。所以应用 lambda 的场合更多是构建一些临时的、简单的和无需复用小函数。虽然原则上可以给 lambda 函数起别名,就像下面这样,以备后续引用。但如果你打算重复利用这个函数,干嘛不用 def 语句定义一个标准函数呢,那样功能更多且更易维护。

>>> foo = lambda a,b: a+b
>>> foo(1,2)
3

filter(), map(), reduce():

apply() 函数因为涉及到可变长参数,并且与这三个函数的作用不同,因此放到最后。filter(), map(), reduce() 这三个内建函数的功能属于一类,都是处理可迭代对象,然后返回结果。

filter(function or None, iterable) --> filter object 的功能就和它的名字一样,使用可迭代对象 iterable 中的每一个元素作为参数来调用布尔函数 function,并将所有返回 True 的元素放在一个迭代器中返回。如果 function 为 None,则将 iterable 中值为 True 的元素返回。例:

>>> a = filter(lambda x:x>2,[1,2,3,4])
>>> type(a)
<class 'filter'>
>>> for i in a:print(i)

3
4
>>>

在以前的版本中 filter() 函数返回的是一个列表,但 Python3 改为了返回一个迭代器,所以上面的例子使用了 for 语句来显示结果。另外返回迭代器的一个注意点就是:上例中的 a 中的元素并不是在赋值的时候一次性生成的,因此如果使用 iterable 的元素调用 function 会产生异常的话,那么该异常实际会在 for 循环中被抛出。可以看到在这种“过滤元素”的应用环境中,我们需要的函数形式非常简单,只有一条表达式,所以使用 lambda 是个不错的选择。(实际下面的两个函数也是一样)

map(func, *iterables) --> map object 的功能是将函数 func 作用于 iterable 的每一个元素,并将结果用迭代器返回。注意这里可以提供多个 iterable,如果这样做,调用 func 的时候就会从每个 iterable 中依次取一个元素,直到最短的 iterable 耗尽。所以这里 func 的参数个数应该等于 iterable 的个数。

>>> a = map(lambda x,y:x+y,[1,2,3],[3,2,1])
>>> type(a)
<class 'map'>
>>> for i in a:print(i)

4
4
4

reduce(function, sequence[, initial]) –> value 的功能是:function 接受两个参数,第一个是 initial,第二个是 sequence 的第一个元素。如果没有提供 initial ,那么就取前两个 sequence 的元素。然后这次调用的返回值再作为第一个参数传递给 function,第二个参数则是 sequence 的下一个元素。这样循环直到 sequence 耗尽,并将最终的值返回。因为 reduce() 函数在 Python3 中已经不是内建函数了,想要使用的话需要 from functools import reduce,所以这里就不举例了。

实际上不只 reduce,这三个函数在现在的版本中都可以说已经没什么用了。filter() 和 map() 都可以由列表解析(生成器表达式)取代,而且明显列表解析更高级好用。所以一般知道这几个函数是干吗用的就够了,基本没必要去实际使用他们。不过下面用来取代 map() 的列表解析示例貌似只能用于单容器的状况,多容器的比如上面那个 map() 的例子该怎么写我想不出。。。

>>> [x for x in [1,2,3,4] if x>2]# filter
[3, 4]
>>> [x+1 for x in [1,2,3]]# map
[2, 3, 4]

apply() 比 reduce() 还惨,在 functools 里都已经不存在了。这是因为早在 1.6 版本他就已经失去作用。我们这里还要提它,仅是为了引出下面的话题:可变长参数。其实在 1.6 以前,函数还不支持可变长参数,而 apply() 就是干这个用的,他可以使用可变长参数来调用函数。

可变长参数:

可变长参数的意思就是:我在调用函数的时候不知道要传多少个参数进来,可能没有,也可能 100 多个。比如一张电子账单,算总额的时候谁知道会有多少项呢。类似这种问题虽然有很多种其他方法把金额加到一起,但使用单一函数来实现总能收获到多余的好处。而且虽然用一个元组也可以实现变长参数的功能,但接下来介绍的方式能做的更好。定义一个函数时可使用的形参完全体如下:

def func(positional_args, keyword_args, *tuple_grp_nonkw_args, **dict_grp_kw_args):

这四种参数形式都是独立可选的。前两个不表,后面带个 * 和带 ** 的就是变长参数了。在位置上,带 * 的必须放在不带 * 的后面,否则会报错。举个栗子,operator 模块里有个 add() 函数:

add(a, b) -- Same as a + b.

该函数只接受两个参数,如果使用可变长参数的话,我们就能让它接受无限个参数并返回他们的和:

>>> def add(*args):
	result = 0
	for num in args:
		result += num
	return result

>>> add(1,2,3,4)
10
>>> add(*(1,2,3,4))
10
>>> add(1,2,*(3,4))
10

从上面的例子可以看出 *tuple_grp_nonkw_args 的作用。只要你的形参里有 *args 这种设定,函数就自动变得对非关键字参数来者不拒。并把接收到的所有参数统一放在一个元组里。

不过这个函数较 operator 里的 add() 有个不足之处,就是那个 add() 除了加数字,还能连接字符串,而我们定义的这个就只能处理数字。于是,接下来就要把位置参数(positional_args)和可变长非关键字参数(*tuple_grp_nonkw_args)一起用了,这也是能体现他们之间联系的一个例子:

>>> def add(first,*args):
	result = first
	checked = type(first)
	for item in [x for x in args if type(x)==checked]:
		result += item
	return result

>>> add(1,2,3,4)
10
>>> add('1','2','3','4')
'1234'
>>> add(1,2,'3','4')
3
>>> add(*(1,2,3,4))
10

这里我们从 *args 里独立出来了一个非关键字参数,并把它命名为 first,再之后的参数只有和 first 同类型的才会加在一起。可以看到这时的 *args 自动让出了第一个参数给 first,而只包含剩余的参数,不论你是单独传入第一个参数,还是用 *()的方式一股脑传入,函数内部对待他们的方式都是一样的。

突然想到上面的例子,int 和 float 参数还是加不到一起。所以可以改一下判定:if type(x) in (int,float) 这样。

而关键字参数的表现和非关键字的一样,这里就不赘述了。

© 著作权归作者所有

共有 人打赏支持
lionets
粉丝 90
博文 96
码字总数 131014
作品 0
朝阳
程序员
Python函数式编程中map()、reduce()和filter()函数的用法

Python中、和三个函数均是应用于序列的内置函数,分别对序列进行遍历、递归计算以及过滤操作。这三个内置函数在实际使用过程中常常和联合使用,我们首先介绍下lambda函数。1、lambda函数 la...

损失函数 ⋅ 05/24 ⋅ 0

python核心编程笔记chapter 11

函数是对程序逻辑进行结构化和过程化的一种编程方法。能将整块代码巧妙地隔离成易于管理的小块。 函数返回多个对象时实际是返回一个包含多个对象的元组。 创建函数: def语句 python不允许在...

MRFung ⋅ 2015/12/31 ⋅ 0

Scala笔记整理(五):函数式编程

[TOC] 作为值传递的函数 测试代码如下: 输出结果如下: 匿名函数 测试代码如下: 输出结果如下: 其实前面在学习ArrayBuffer的时候已经有使用过匿名函数: 带函数参数的函数(高阶函数) 说...

xpleaf ⋅ 04/21 ⋅ 0

python核心编程-第十一章-个人笔记(一)

调用函数 1.1 关键字参数和默认参数 关键字参数调用函数允许用户缺失参数或者不按顺序给定参数。默认参数则是声明了默认值的参数。如下例: def power(a, b=2): print a ** b power(b=3,a=4)...

好好先生_1028 ⋅ 2016/04/23 ⋅ 0

Python函数式编程

虽然 Python 不是函数式编程语言(是命令式编程语言),但是支持许多有价值的函数式编程工具。Python 提供 3 种内建函数和 lambda 表达式等来支持函数式编程。 匿名函数 Python 允许用 lamb...

Jeffbond ⋅ 2017/03/15 ⋅ 0

python核心编程--第十一章

11.1.2 返回值与函数类型 过程可理解为函数,返回none 下面代码可简单理解函数返回值的概念: >>> defhello(): res =hello()hello world!>>> printresNone>>>type(res)<type'NoneType'>>>> ......

fzyz_sb ⋅ 2013/06/17 ⋅ 2

fluent python- 5 一等函数-面向对象(附第四章-文本和字节序列)

第 4 章 文本和字节序列 人类使用文本, 计算机使用字节序列。 第 5 章 一等函数 前言: 在 Python 中, 函数是一等对象。 编程语言理论家把“一等对象”定义为满足下述条件的程序实体: 1、...

时间之友 ⋅ 2017/12/03 ⋅ 0

python函数式编程

1, lambda lambda可以创建匿名函数,一个完整的lambda表达式格式如下: lambda [arg1[, arg2, ... argN]]: 返回值 lambda表达式返回一个可调用的函数对象。 >>> func = lambda x:x*2>>> func<......

Si2 ⋅ 2014/01/27 ⋅ 0

Python 进阶语法四 —— Map、Filter和Reduce

四、Map、Filter和Reduce Map、Filter和Reduce三个函数能为函数式编程提供便利。我们会通过实例一个一个讨论并理解它们。 Map Map会将一个函数映射到一个输入列表的所有元素上。这是它的规范...

东方神剑 ⋅ 2016/11/27 ⋅ 0

[Python]学习基础篇:函数的进阶篇

对于函数大家都熟知不过了,但是对于一些函数还是费力的理解,下来我们来看看Python自带的一些函数,在此之前,还是请大家了解什么是高阶函数。 高阶函数:函数中的高阶函数 map()函数 格式:...

Insane_linux ⋅ 01/07 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Centos7重置Mysql 8.0.1 root 密码

问题产生背景: 安装完 最新版的 mysql8.0.1后忘记了密码,向重置root密码;找了网上好多资料都不尽相同,根据自己的问题总结如下: 第一步:修改配置文件免密码登录mysql vim /etc/my.cnf 1...

豆花饭烧土豆 ⋅ 今天 ⋅ 0

熊掌号收录比例对于网站原创数据排名的影响[图]

从去年下半年开始,我在写博客了,因为我觉得业余写写博客也还是很不错的,但是从2017年下半年开始,百度已经推出了原创保护功能和熊掌号平台,为此,我也提交了不少以前的老数据,而这些历史...

原创小博客 ⋅ 今天 ⋅ 0

LVM讲解、磁盘故障小案例

LVM LVM就是动态卷管理,可以将多个硬盘和硬盘分区做成一个逻辑卷,并把这个逻辑卷作为一个整体来统一管理,动态对分区进行扩缩空间大小,安全快捷方便管理。 1.新建分区,更改类型为8e 即L...

蛋黄Yolks ⋅ 今天 ⋅ 0

Hadoop Yarn调度器的选择和使用

一、引言 Yarn在Hadoop的生态系统中担任了资源管理和任务调度的角色。在讨论其构造器之前先简单了解一下Yarn的架构。 上图是Yarn的基本架构,其中ResourceManager是整个架构的核心组件,它负...

p柯西 ⋅ 今天 ⋅ 0

uWSGI + Django @ Ubuntu

创建 Django App Project 创建后, 可以看到路径下有一个wsgi.py的问题 uWSGI运行 直接命令行运行 利用如下命令, 可直接访问 uwsgi --http :8080 --wsgi-file dj/wsgi.py 配置文件 & 运行 [u...

袁祾 ⋅ 今天 ⋅ 0

JVM堆的理解

在JVM中,我们经常提到的就是堆了,堆确实很重要,其实,除了堆之外,还有几个重要的模块,看下图: 大 多数情况下,我们并不需要关心JVM的底层,但是如果了解它的话,对于我们系统调优是非常...

不羁之后 ⋅ 昨天 ⋅ 0

推荐:并发情况下:Java HashMap 形成死循环的原因

在淘宝内网里看到同事发了贴说了一个CPU被100%的线上故障,并且这个事发生了很多次,原因是在Java语言在并发情况下使用HashMap造成Race Condition,从而导致死循环。这个事情我4、5年前也经历...

码代码的小司机 ⋅ 昨天 ⋅ 2

聊聊spring cloud gateway的RetryGatewayFilter

序 本文主要研究一下spring cloud gateway的RetryGatewayFilter GatewayAutoConfiguration spring-cloud-gateway-core-2.0.0.RC2-sources.jar!/org/springframework/cloud/gateway/config/G......

go4it ⋅ 昨天 ⋅ 0

创建新用户和授予MySQL中的权限教程

导读 MySQL是一个开源数据库管理软件,可帮助用户存储,组织和以后检索数据。 它有多种选项来授予特定用户在表和数据库中的细微的权限 - 本教程将简要介绍一些选项。 如何创建新用户 在MySQL...

问题终结者 ⋅ 昨天 ⋅ 0

android -------- 颜色的半透明效果配置

最近有朋友问我 Android 背景颜色的半透明效果配置,我网上看资料,总结了一下, 开发中也是常常遇到的,所以来写篇博客 常用的颜色值格式有: RGB ARGB RRGGBB AARRGGBB 这4种 透明度 透明度...

切切歆语 ⋅ 昨天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部