首页 > 代码库 > lambda表达式

lambda表达式

lambda表达式

  lambda表达式就是能嵌入到其他表达式当中的匿名函数(闭包)

意义:

1、可以在表达式当中直接定义一个函数,而不需要将定义函数和表达式分开,这个函数只是一个临时的函数。
2、引入了闭包。基本上常见的支持lambda表达式的语言里,不存在不支持闭包的lambda表达式;从函数式编程的角度来说,支持闭包也是很重要的。
如果在一个内部函数里,对在外部作用域(但不是在全局作用域)的变量进行引用,那么内部函数就被认为是闭包(closure),它使你的lambda表达式从一个普通的函数变成了一个带隐藏参数的函数。

创建语法:

lambda parameters:express

parameters:可选,如果提供,通常是逗号分隔的变量表达式形式,即位置参数。

expression:不能包含分支或循环(但允许条件表达式),也不能包含return(或yield)函数。如果为元组,则应用圆括号将其包含起来。

实例(实验环境为Python3.6)

两数求和:

#lambda
>>>my_lambda = lambda x,y;x+y
#执行
>>>result = my_lambda(1,2)
result=3

求n的阶乘:

>>>n=5
>>>reduce(lambda x,y:x*y, range(1,n+1)
120

把lambda 作为返回表达式

>>> b=lambda x:lambda y:x+y
>>>a=b(3)
>>>a(2)
5
>>>(b(2))(2)
4

 

内建函数:(map,reduce,filter,sorted)

map()函数接收两个参数,一个是函数,一个是序列,map将传入的函数依次作用到序列的每个元素,并把结果作为新的list返回

(python3.6)

>>> list(map(lambda x:x*x,[1,2,3,4,5,6,7,8,9]))
[1, 4, 9, 16, 25, 36, 49, 64, 81]

技术分享

reduce()把一个函数作用在一个序列[x1, x2, x3...]上,这个函数必须接收两个参数,reduce把结果继续和序列的下一个元素做累积计算,其效果就是:

reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)

比如上面的求阶乘的代码。

字符串str也是一个序列,我们可以写一个吧str转换成int的函数:(python3.6)

>>> def char2num(s):
...     return {0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9}[s]
...
>>> from functools import reduce
>>> reduce(lambda x,y:x*10+y,map(char2num,13579))
13579

filter()函数接收一个函数 f 和一个list,这个函数 f 的作用是对每个元素进行判断,返回 True或 False,filter()根据判断结果自动过滤掉不符合条件的元素,返回由符合条件元素组成的新list。

 写一个从list[1,2,3,4,5,6]中删除偶数,保留奇数的程序(Python3.6)

>>> list(filter(lambda x:x%2==1,[1,2,3,4,5,6]))
... 
[1, 3, 5]

排序函数 sorted()和list.sort[]

 python中,具体到对list进行排序的方法有俩,一个是list自带的sort方法,这个是直接对list进行操作,只有list才包含的方法;另外一个是内建函数sorted方法,可以对所有可迭代的对象进行排序操作,在本质上,list的排序和内建函数sorted的排序是差不多的,连参数都基本上是一样的

 主要的区别在于,list的sort方法返回的是对已经存在的列表进行操作,而内建函数sorted方法返回的是一个新的list,而不是在原来的基础上进行的操作。

>>> help(sorted)
Help on built-in function sorted in module builtins:

sorted(iterable, key=None, reverse=False)
    Return a new list containing all items from the iterable in ascending order.

    A custom key function can be supplied to customize the sort order, and the
    reverse flag can be set to request the result in descending order.

Python3中去除了cmp内置函数,同时sorted等函数也去除了cmp关键字,添加key关键字 

使用sorted()方法和list.sort()方法进行排序
elements=[(2,12,"A"),(1,11,"N"),(1,3,"L"),(2,4,"B")]
>>> sorted(elements)
[(1, 3, L), (1, 11, N), (2, 4, B), (2, 12, A)]
 
根据elements每个元组后两项进行排序,e表示列表中每个三元组元素
在表达式是元组,且lambda为一个函数的参数时,lambda表达式的圆括号是必需的
>>> elements.sort(key=lambda e:(e[1],e[2]))
>>> elements
[(1, 3, L), (2, 4, B), (1, 11, N), (2, 12, A)]
 
分片方式得到同样的效果
>>> elements.sort(key=lambda e:e[1:3])
>>> elements
[(1, 3, L), (2, 4, B), (1, 11, N), (2, 12, A)]
 
>>> elements.sort(key=lambda e:(e[2].lower(),e[1]))
以下两种方法等价,都可以通过调用area(5,3),结果相同
>>> area=lambda b,h:0.5*b*h
>>> def area(b,h):
    return 0.5*b*h

闭包(简单介绍一下闭包)

在一个内部函数中,对外部作用域的变量进行引用,(并且一般外部函数的返回值为内部函数),那么内部函数就被认为是闭包,举个栗子(以一个类似棋盘游戏的例子来说明。假设棋盘大小为50*50,左上角为坐标系原点(0,0),我需要一个函数,接收2个参数,分别为方向(direction),步长(step),该函数控制棋子的运动。 这里需要说明的是,每次运动的起点都是上次运动结束的终点。):

>>> origin=[0,0]
>>> def create(pos=origin):
... def go(direction,step):
... new_x=pos[0]+direction[0]*step
... new_y=pos[1]+direction[1]*step
... pos[0]=new_x
... pos[1]=new_y
... return pos
... return go
...
>>> player = create()
>>> print(player([1,0],10))
[10, 0]
>>> print(player([0,1],20))
[10, 20]
>>> print(player([-1,0],10))
[0, 20]

>>>print(‘player:‘,player)

function: <function create.<locals>.go at 0x02F94660>

>>> print(‘function:‘,go)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name ‘go‘ is not defined
>>> print(‘function:‘,create)
function: <function create at 0x02E4D540>

注意:

  • 闭包无法修改外部函数的局部变量
  • python循环中不包含域的概念
  • 闭包可以保存当前的运行环境

 

#
>>> def outerFunc():
...     x = 0
...     def innerFunc():
...             x = 1
...             print(inner x:,x)
...     print(outer x before call inner:,x)
...     innerFunc()
...     print(outer x after call inner:,x)
...
>>>
>>> outerFunc()
outer x before call inner: 0
inner x: 1
outer x after call inner: 0
>>>
#按照正常的理解下面的程序应该输入0,2,4,对吧? 但实际输出的是4,4,4,循环在Python中没有遇到概念,flist在向列表中添加func的时候,并没有保存i的值而当执行f(2)的时候才去取,这时候循环已经结束,i的值是2,所以结果都是4
>>> flist = []>>> for i in range(3):
...     def func(x):
...             return x*i
...     flist.append(func)
...
>>> for f in flist:
...     print(f(2))
...
4
4
4
#修改方案
>>> flist = []
>>> for i in range(3):
...     def makefunc(i):
...             def func(x):
...                     return x*i
...             return func
...     flist.append(makefunc(i))
...
>>> for f in flist:
...     print(f(2))
...
0
2
4
>>>
#(f是一个函数 序列) 在func外面再定义一个makefunc函数,func形成闭包

 

lambda表达式