匿名函数详细讲解

来源:互联网 发布:js rowindex 编辑:程序博客网 时间:2024/06/06 03:24

lambda这个名称来自于LISP,而LISP则是从lambda calculus(一种符号逻辑形式)取这个名称的。在Python中,
lambda作为一个关键字,作为引入表达式的语法。想比较def函数,lambda是单一的表达式,而不是语句块!
你仅能够在lambda中封装有限的业务逻辑,这样设计的目的:让lambda纯粹为了编写简单的函数而设计,def则
专注于处理更大的业务。

在编程语言中,函数的应用:
1. 代码块重复,这时候必须考虑用到函数,降低程序的冗余度
2. 代码块复杂,这时候可以考虑用到函数,降低程序的可读性
在Python,有两种函数,一种是def定义,一种是lambda函数(一种生成函数对象的表达式形式,因为她和LISP语言很相似,所以取名字为lambda函数)

假如要求两个数之和,用普通函数或匿名函数如下:


  1. def func(x,y):return x+y
  2. lambda x,y: x+y
    在编程语言中,C/C++/Java属于过程式编程,而匿名函数(lambda)一般应用于函数式编程中,举个简单例子也许比较好理解,对于一个列表,要求大于3的元素.
    过程式编程实现: 也就是常规的方法
    [python] view plain copy

L1 = [1,2,3,4,5]
L2 = []
for i in L1:
if i>3:
L2.append(i)
L2
[4, 5]
函数式编程实现: 运用filter,给其一个判断条件即可
def func(x): return x>3 #在函数中
filter(func,[1,2,3,4,5])
[4, 5]
如果运用匿名函数,则更加精简,一行就可以了:
filter(lambda x:x>3,[1,2,3,4,5])
[4, 5]
总结: 从中可以看出,lambda一般应用于函数式编程,代码简洁,常和reduce,filter等函数结合使用。
格式如下:
lambda argument1, argument2,… argumentN :expression using arguments
解构上面的例子
x 为lambda函数的一个参数
: 分割符
x>3 则是返回值,在lambda函数中不能有return,其实:后面就是返回值
为什么要用匿名函数?
1. 程序一次行使用,所以不需要定义函数名,节省内存中变量定义空间
2. 如果想让程序更加简洁时。
匿名函数几个规则:
1. 一般也就一行表达式,必须有返回值
2. 不能有return
3. 可以没有参数,可以有一个或多个参数
def func(x): x+y
func

lambda x: x+y

无参匿名函数:

t = lambda : True #分号前无任何参数
t()
True
等价于下面的def定义的函数
def func(): return True
func()

True

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”)
带参数匿名函数
lambda x: x**3 #一个参数
lambda x,y,z:x+y+z #多个参数
lambda x,y=3: x*y #允许参数存在默认值
匿名函数调用

直接赋值给一个变量,然后再像一般函数调用


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!’
大量例子:
例01: 字符串联合,有默认值,也可以x=(lambda…)这种格式
x = (lambda x=”Boo”,y=”Too”,z=”Zoo”: x+y+z)
x(“Foo”)
‘FooTooZoo’
例02: 和列表联合使用
L = [lambda x:x**2,\
lambda x:x**3,\
lambda x:x**4]
for f in L:
… print f(2)

4
8
16
也可以如下面这样调用
print L0
9
例03: 和字典结合使用
key = ‘B’
dic = { ‘A’: lambda: 2*2,\
… ‘B’: lambda: 2*4,\
… ‘C’: lambda: 2*8}
dickey
8
例04: 求最小值
lower = lambda x,y: x if x

True

Names = [‘Anne’, ‘Amy’, ‘Bob’, ‘David’, ‘Carrie’, ‘Barbara’, ‘Zach’]
B_Name= filter(lambda x: x.startswith(‘B’),Names)
B_Name
[‘Bob’, ‘Barbara’]
例09: lambda和map联合使用:
squares = map(lambda x:x**2,range(5))
squares
[0, 1, 4, 9, 16]
例10. lambda和map,filter联合使用:
squares = map(lambda x:x**2,range(10))
filters = filter(lambda x:x>5 and x<50,squares)
filters
[9, 16, 25, 36, 49]
例11. lambda和sorted联合使用

按death名单里面,按年龄来排序

匿名函数的值返回给key,进来排序

death = [ (‘James’,32),
(‘Alies’,20),
(‘Wendy’,25)]
sorted(death,key=lambda age:age[1]) #按照第二个元素,索引为1排序
[(‘Alies’, 20), (‘Wendy’, 25), (‘James’, 32)]
例12. lambda和reduce联合使用
L = [1,2,3,4]
sum = reduce(lambda x,y:x+y,L)
sum
10
例13. 求2-50之间的素数

素数:只能被1或被自己整除的数

nums = range(2,50)
for i in nums:
nums = filter(lambda x:x==i or x % i,nums)
nums
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]
例14. 求两个列表元素的和
a = [1,2,3,4]
b = [5,6,7,8]
map(lambda x,y:x+y, a,b)
[6, 8, 10, 12]
例15. 求字符串每个单词的长度
sentence = “Welcome To Beijing!”
words = sentence.split()
lengths = map(lambda x:len(x),words)
lengths
[7, 2, 8]
写成一行:
print map(lambda x:len(x),’Welcome To Beijing!’.split())
例16. 和def函数一起使用,注意其参数传递
[python] view plain copy
def sayHello():
… title = ‘Hello, ’
… union = (lambda x: title + ” + x + ‘!’)
… return union

f = sayHello() #此处无需带参数
f(‘Jerry’) #通过修改默认参数来传递参数
‘Hello, Jerry!’
例17. 统计Linux系统挂载点
[root@host ~]# mount -v
/dev/mapper/rootVG-root on / type ext3 (rw)
proc on /proc type proc (rw)
sysfs on /sys type sysfs (rw)
devpts on /dev/pts type devpts (rw,gid=5,mode=620)
/dev/mapper/rootVG-tmp on /tmp type ext3 (rw)
/dev/mapper/rootVG-var on /var type ext3 (rw)
/dev/cciss/c0d0p1 on /boot type ext3 (rw)
tmpfs on /dev/shm type tmpfs (rw,size=90%)

import commands
mount = commands.getoutput(‘mount -v’)
lines = mount.splitlines()
point = map(lambda line:line.split()[2],lines)
print point
[‘/’, ‘/proc’, ‘/sys’, ‘/dev/pts’, ‘/tmp’, ‘/var’]
写成一行:
print map(lambda x:x.split()[2],commands.getoutput(‘mount -v’).splitlines())
效率问题:

比较def函数和lambda函数效率问题

[objc] view plain copy
import time

测试的Def函数

def square1(n):
return n ** 2

测试的Lambda函数

square2 = lambda n: n ** 2

print(time.time())

使用Def函数

i = 0
while i < 1000000000:
square1(100)
i += 1

print(time.time())

使用lambda函数

i = 0
while i < 1000000000:
square2(100)
i += 1

print(time.time())
输出结果:
1413272496.27
1413272703.05 (Def 函数:207s)
1413272904.49 (Lambda函数:201s)
从上面可以看出,两者的所需的时间差不多,效率丝毫不受影响.

晦涩属性:
出于简明的考虑,避免在lambda中嵌套lambda
[python] view plain copy

action = (lambda x: (lambda y: x+ y))
action(99)(2)
101
像上面的例子,出于代码的简洁性考虑,最好换成下面的
[python] view plain copy
def f(x):
… return (lambda y: x + y)

g = f(99)
g(2)
101
难点例子:
from itertools import product
map(lambda p: ”.join(i + j for i, j in zip(‘abcd’, p)) + ‘e’, product([‘.’, ”], repeat = 4))

原创粉丝点击