lambda用法及其高阶函数
lambda函数
1、lambda 语法
lambda arg1,arg2,…argn(传入的参数):expression(要执行的语句)
匿名函数不需要return来返回值,表达式expression执行完的结果就是返回值。
# 普通python函数
def func(a,b,c):
return a+b+c
print func(1,2,3)
# 返回值为6
# lambda匿名函数
f = lambda a,b,c:a+b+c
print f(1,2,3)
# 返回结果为6
1.1 参数arg
[arg…] 是参数列表,它的结构与 Python 中函数(function)的参数列表是一样的。
[arg…] 可以有非常多的形式。例如:
a, b函数输入是a和ba=1, b=2*args输入是任意个数参数**kwargs输入是任意键值对参数a, b=1, *args空函数没有输入参数- …
1.2 参数表达式expression
expression 是一个参数表达式,表达式中出现的参数需要在[arg......]中有定义,并且表达式只能是单行的,只能有一个表达式。
以下都是合法的表达式:
- 1
- None
- a + b
- sum(a)
- 1 if a >10 else 0
- m for m in xxxxx
- …
1.3 常见的lambda函数示例:
lambda x, y: x*y # 函数输入是x和y,输出是它们的积x*y
lambda:None # 函数没有输入参数,输出是None
lambda *args: sum(args) # 输入是任意个数参数,输出是它们的和(隐性要求输入参数必须能进行算术运算)
lambda **kwargs: 1 # 输入是任意键值对参数,输出是1
无参匿名函数
例1、
无参匿名函数:
------
>>> t = lambda : True #分号前无任何参数
>>> t()
True
等价于下面的def定义的函数
>>> def func(): return True
>>> func()
True
例2、
#建此字符串按照正常情形输出
>>> s = "this is\na\ttest"
>>> s
'this is\na\ttest'
>>> print s.split() #split函数默认分割:空格,换行符,TAB
['this', 'is', 'a', 'test']
>>> ' '.join(s.split()) #用join函数将一个列表转为字符串
'this is a test'
等价于
>>> (lambda s:' '.join(s.split()))("this is\na\ttest")
即
f = lambda s:' '.join(s.split());
f("this is\na\ttest")
带参匿名函数
>>> lambda x: x**3 #一个参数
>>> lambda x,y,z:x+y+z #多个参数
>>> lambda x,y=3: x*y #允许参数存在默认值
#以元组作为参数
>>> a = lambda *z:z #参数*z表示输入参数为元组
>>> a('Testing1','Testing2')
('Testing1', 'Testing2')
匿名函数调用
#直接赋值给一个变量,然后再像一般函数调用
>>> c = lambda x,y,z: x*y*z
>>> c(2,3,4)
24
------
>>> c = lambda x,y=2: x+y #使用了默认值
>>> c(10) #不输的话,使用默认值2
12
------
>>> a = lambda *z:z #*z返回的是一个元祖
>>> a('Testing1','Testing2')
('Testing1', 'Testing2')
------
>>> c = lambda **Arg: Arg #arg返回的是一个字典
>>> c()
{}
#直接后面传递实参
------
>>> (lambda x,y: x if x> y else y)(101,102)
102
------
>>> (lambda x:x**2)(3)
9
#lambda返回的值,结合map,filter,reduce使用
>>> filter(lambda x:x%3==0,[1,2,3,4,5,6])
[3, 6]
等价于下面的列表推导式
>>> l = [x for x in [1,2,3,4,5,6] if x%3==0]
>>> l
[3, 6]
嵌套使用
#lambda嵌套到普通函数中,lambda函数本身做为return的值
------
>>> def increment(n):
... return lambda x: x+n
...
>>> f=increment(4)
>>> f(2)
6
------
>>> def say():
... title = 'Sir,'
... action= lambda x: title + x
... return action
...
>>> act = say()
>>> act('Smith!')
'Sir,Smith!'
2、lambda 用法之高阶函数
2.1 map() 函数:
map(function, iterable, ...)
描述:map() 会根据提供的函数function 对指定序列 iterable 做映射。
以序列中的每一个元素调用 function 函数,返回包含每次 function 函数返回值的新列表。
参数:
-
function ----> 函数
-
iterable ----> 一个或多个序列
返回值:
- Python 2.x 版本返回的是列表
- Python 3.x 版本返回的是迭代器
# ===========一般写法:===========
# 1、计算平方数
def square(x):
return x ** 2
map(square, [1,2,3,4,5]) # 计算列表各个元素的平方
# 结果:
[1, 4, 9, 16, 25]
# ===========匿名函数写法:============
# 2、计算平方数,lambda 写法
map(lambda x: x ** 2, [1, 2, 3, 4, 5])
# 结果:
[1, 4, 9, 16, 25]
# 3、提供两个列表,将其相同索引位置的列表元素进行相加
map(lambda x, y: x + y, [1, 3, 5, 7, 9], [2, 4, 6, 8, 10])
# 结果:
[3, 7, 11, 15, 19]
2.2 reduce()函数
reduce(function, iterable[, initializer])
-
reduce() 函数会对参数序列中元素进行 累加。
-
函数将一个数据集合(链表,元组等)中的所有数据进行下列操作:
- 用传给 reduce 中的函数 function(有两个参数)先对集合中的第 1、2 个元素进行操作,
- 得到的结果再与第三个数据用 function 函数运算,以此类推,最后得到一个结果。
参数:
- function ----> 函数,有两个参数
- iterable ----> 可迭代对象
- initializer ----> 可选,初始参数
返回值:
- 返回函数计算结果。
# ===========一般写法:===========
# 1、两数相加
def add(x, y):
return x + y
reduce(add, [1, 3, 5, 7, 9]) # 计算列表元素和:1+3+5+7+9
# 结果:
25
"""
===========执行步骤解析:===========
调用 reduce(add, [1, 3, 5, 7, 9])时,reduce函数将做如下计算:
1 先计算头两个元素:f(1, 3),结果为4;
2 再把结果和第3个元素计算:f(4, 5),结果为9;
3 再把结果和第4个元素计算:f(9, 7),结果为16;
4 再把结果和第5个元素计算:f(16, 9),结果为25;
5 由于没有更多的元素了,计算结束,返回结果25。
"""
# ===========匿名函数写法:===========
# 2、两数相加,lambda 写法
reduce(lambda x, y: x + y, [1, 2, 3, 4, 5])
# 结果:
15
什么时候用reduce()?
# 当然求和运算可以直接用Python内建函数sum(),没必要动用reduce。
# 3、但是如果要把序列 [1, 3, 5, 7, 9] 变换成整数 13579,reduce就可以派上用场:
def fn(x, y):
return x * 10 + y
reduce(fn, [1, 3, 5, 7, 9])
# 结果:
13579
2.3 sorted() 函数:
sorted(iterable[, cmp[, key[, reverse]]])
描述: sorted() 函数对所有可迭代的对象进行排序操作。
sort 与 sorted 区别:
sort 是 list 的一个方法,而 sorted 可以对 所有 可迭代的对象进行排序操作。
list 的 sort 方法返回的是对已经存在的列表进行操作,无返回值,而内建函数 sorted 方法返回的是一个 新的 list,而不是在原来的基础上进行的操作。
参数说明:
- iterable ----> 可迭代对象。
- cmp ----> 比较的函数,这个具有两个参数,参数的值都是从可迭代对象中取出,此函数必须遵守的规则为,大于则返回1,小于则返回-1,等于则返回0。
- key ----> 主要是用来进行比较的元素,只有一个参数,具体的函数的参数就是取自于可迭代对象中,指定可迭代对象中的一个元素来进行排序。
- reverse ----> 排序规则,reverse = True 降序 , reverse = False 升序(默认)。
返回值:
返回重新排序的列表。
# ===========一般用法:===========
# 1、简单排序
a = [5,7,6,3,4,1,2]
b = sorted(a) # 使用sorted,保留原列表,不改变列表a的值
print(a)
[5, 7, 6, 3, 4, 1, 2] # 原列表不变
print(b)
[1, 2, 3, 4, 5, 6, 7]
# ===========匿名函数用法:===========
L=[('b',2),('a',1),('c',3),('d',4)]
# 2、利用参数 cmp 排序
sorted(L, cmp=lambda x,y:cmp(x[1],y[1]))
# 结果:
[('a', 1), ('b', 2), ('c', 3), ('d', 4)]
---------
# 3、利用参数 key 排序
sorted(L, key=lambda x:x[1])
# 结果:
[('a', 1), ('b', 2), ('c', 3), ('d', 4)]
---------
# 4、按年龄升序
students = [('john', 'A', 15), ('jane', 'B', 12), ('dave', 'B', 10)]
sorted(students, key=lambda s: s[2])
# 结果:
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]
---------
# 5、按年龄降序
sorted(students, key=lambda s: s[2], reverse=True)
# 结果:
[('john', 'A', 15), ('jane', 'B', 12), ('dave', 'B', 10)]
2.4 filter() 函数:
filter(function, iterable)
描述: filter() 函数用于过滤序列,过滤掉不符合条件的元素,返回由符合条件元素组成的新列表。
-
该接收两个参数,第一个为函数,第二个为序列,
-
序列的每个元素作为参数传递给函数进行判,然后返回 True 或 False,
-
最后将返回 True 的元素放到新列表中。
参数:
- function ----> 判断函数。
- iterable ----> 可迭代对象。
返回值:
- Pyhton2.7 返回列表,
- Python3.x 返回迭代器对象,具体内容可以查看:Python3 filter() 函数
# ===========一般用法:===========
# 1、过滤出列表中的所有奇数
def is_odd(n):
return n % 2 == 1
newlist = filter(is_odd, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
print(list(newlist))
# 结果: [1, 3, 5, 7, 9]
# ===========匿名函数用法:===========
# 2、将列表[1, 2, 3]中能够被3整除的元素过滤出来
newlist = filter(lambda x: x % 3 == 0, [1, 2, 3])
print(list(newlist))
# 结果: [3]
2.5 和for连用
(1)res=[ lambda x,i=i : x*i for i in range (6) ]
第一种:带参数x
res=[ lambda x,i=i : x*i for i in range (6) ]
- res=[ lambda x,i=i : x*i for i in range (6) ] ,获得一个函数列表
- res[0]代表 i = 0时计算x*0的值;同理, res[1],…, res[5] 分别代表 i = 1,…,5 时的函数
res[1](0)即 向函数res[1]传入参数0。
例1: 给出一个值 x ,分别计算 x 与 0~5 之间各个数的乘积
# 给出一个值 x ,分别计算 x 与 0~5 之间各个数的乘积
res=[lambda x,i=i : x*i for i in range (6)]
print(res) #得到返回 x*i 函数的6个地址
for f in res: #循环遍历每个地址
print(f(2)) #对每个遍历到的函数 传递参数 x=2
#0 2 4 6 8 10
输出:0 2 4 6 8 10
这里的x+i for i in range (6)是原for…in…if…的用法
x,i为每个函数的参数,而 i 由for循环指定
相当于:
res = []
for i in range(4):
def lam(x,y=i): # 即 指定y=i
return x*y # 即 x*i
fs.append(lam)
for f in res: #循环遍历每个地址
print(f(2)) #对每个遍历到的函数 传递参数 x=2
# 输出:0 2 4 6 8 10
输出:0 2 4 6 8 10
第二种:无参使用:
res = [lambda i=i: i*i for i in range(6)]
调用时无需输入参数,但是注意括号不能少!
res = [lambda i=i: i*i for i in range(6)]
for f in res: #循环遍历每个地址
print(f()) #无需输入参数,但是注意 括号不能少!
输出:0 1 4 9 16 25
相当于:
fs = []
for i in range(4):
def lam(x=i): # 即 i=i
return x*x # 即 i*i
fs.append(lam)
(2)错误操作:res = [lambda x : x*i for i in range(6)]
第一种:带参数x
res = [lambda x : x*i for i in range(6)]
print(res) # 获得一个包含 x*i 函数的6个地址的列表。
for f in res: #循环遍历每个地址
print(f(2)) #对每个遍历到的函数 传递参数 x=2
输出:10 10 10 10 10 10
相当于:
res = []
for i in range (6):
def lam(x): #并未指定另一个参数i的值
return x*i
res.append(lam)
for f in res: #循环遍历每个地址
print(f(2)) #对每个遍历到的函数 传递参数 x=2
每循环一次,将 lam 函数的地址存到 res 中。因为在每次循环中 lam函数都未绑定 i 的值,所以直到循环结束,i 的值为5,并将 lam 中所用到的 i 值定为 5 ,因此真正调用(例如res[0](2)的时候 i 值保持不变(为5)。
所以 无论调用的res[]是第几个函数,计算的都是 x*5。
第二种:无参使用:
res= [lambda : i*i for i in range(6)]
无需输入参数,但是注意 括号不能少!
res= [lambda : i*i for i in range(6)]
for f in res: #循环遍历每个地址
print(f()) #无需输入参数,但是注意 括号不能少!
#25 25 25 25 25 25
输出:25 25 25 25 25 25
相当于:
res = []
for i in range (6):
def lam(): #并未指定i的值
return i*i
res.append(lam)
for f in res: #循环遍历每个地址
print(f())
# 输出:25 25 25 25 25 25
输出:25 25 25 25 25 25
(3)res = lambda x : [x*i for i in range(6)]
这种就比较正常啦!
只会获得一个函数,而不是(1)(2)中的函数列表
中括号括起来的只是表达式部分。
第一种:带参数x
res = lambda x : [x*i for i in range(6)]
res = lambda x : [x*i for i in range(6)]
res(2)
# 输出:[0, 2, 4, 6, 8, 10]
输出:[0, 2, 4, 6, 8, 10]
相当于
def res(x):
return [x*i for i in range(6)]
res(2)
# 输出:[0, 2, 4, 6, 8, 10]
第二种:无参使用:
res = lambda : [x for x in range(5)]
- 只获得一个函数,其中函数表达式是
[x for x in range(5)] - 无需输入参数
res = lambda : [x for x in range(5)]
res()
输出:[0, 1, 2, 3, 4]
相当于 直接return这个列表推导式
def res():
return [x for x in range(5)]
res()
3、复习一下列表推导式:for…in…if语法(不使用lambda)
[expression for x in X [if condition] for y in Y [if condition] ... for n in N [if condition]]
上面按照从左至右的顺序,分别是外层循环到内层循环
称为 列表推导式
2.6.1 带有 if 语句
可以在 for 语句后面跟上一个 if 判断语句,用于过滤掉那些不满足条件的结果项。
例如,我想去除列表中所有的偶数项,保留奇数项,可以这么写:
>>> L = [1, 2, 3, 4, 5, 6]
>>> L = [x for x in L if x % 2 != 0]
>>> L
[1, 3, 5]
2.6.2 带有 for 嵌套
在复杂一点的列表推导式中,可以嵌套有多个 for 语句。按照从左至右的顺序,分别是外层循环到内层循环。
例如:
>>> [x + y for x in 'ab' for y in 'jk']
['aj', 'ak', 'bj', 'bk']
2.6.3. 既有 if 语句又有 for 嵌套: for…in…if…
列表推导式可以带任意数量的嵌套 for 循环,并且每一个 for 循环后面都有可选的 if 语句。
通用语法:
[ expression for x in X [if condition]
for y in Y [if condition]
...
for n in N [if condition] ]
例如,下面的代码输出了 0~4 之间的偶数和奇数的组合。
>>> [(x, y) for x in range(5) if x % 2 == 0 for y in range(5) if y % 2 == 1]
[(0, 1), (0, 3), (2, 1), (2, 3), (4, 1), (4, 3)]
等价于下面的一般 for 循环:
>>> L = []
>>> for x in range(5):
... if x % 2 == 0:
... for y in range(5):
... if y % 2 == 1:
... L.append((x, y))
>>> L
[(0, 1), (0, 3), (2, 1), (2, 3), (4, 1), (4, 3)]
2.6.4. 列表推导式生成矩阵
生成矩阵的方式有多种,例如手动赋值、一般 for 循环,还有就是列表推导式。如果我们要用列表推导式生成下面的矩阵,可以怎么写?
>>> M = [[1, 2, 3],
... [4, 5, 6],
... [7, 8, 9]]
一种方法是:
>>> M = [[x, x+1, x+2] for x in [1, 4, 7]]
>>> M
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
矩阵的列数少时可以使用这种方法。
如果矩阵的列数较多,我们可以使用另外一种方式:在循环变量的表达式中使用列表推导式。
具体代码如下:
>>> M = [[y for y in range(x, x+3)] for x in [1, 4, 7]]
>>> M
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
123
与之前带 for 嵌套的语法不同,这个例子中,实际使用的是最基本的 [expression for x in L] 语法,只有一个 for 语句。
复杂的地方在于前面的变量表达式 expression 不再是简单的变量运算,而是一个列表推导式,在这个例子中就是 [y for y in range(x, x+3)] 。
内层的列表推导式返回一个行向量,而这些行向量经由外层的列表推导式,最终形成一个二维列表,也就是我们想要的矩阵。
参考:
Python 之 lambda 函数完整详解 & 巧妙运用_lambda函数python_Nick Peng的博客-CSDN博客