Python匿名函数详解

转载自杰瑞的专栏

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的元素.

过程式编程实现: 也就是常规的方法

  1. >>> L1 = [1,2,3,4,5]
  2. >>> L2 = []
  3. >>> for i in L1:
  4. if i>3:
  5. L2.append(i)
  6. >>> L2
  7. [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
<function func at 0x0000000002F48DD8>
>>> lambda x: x+y
<function <lambda> at 0x0000000002F48D68>

无参匿名函数:

------

>>> 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 L[0](3)
9

  • 例03: 和字典结合使用

>>> key = ‘B‘
>>> dic = { ‘A‘: lambda: 2*2,\
...         ‘B‘: lambda: 2*4,\
...         ‘C‘: lambda: 2*8}
>>> dic[key]()
8

  • 例04: 求最小值

>>> lower = lambda x,y: x if x<y else y
>>> lower(‘aa‘,‘ab‘)
‘aa‘

  • 例05: 和map及list联合使用

>>> import sys
>>> showall = lambda x:list(map(sys.stdout.write,x))
>>> showall([‘Jerry\n‘,‘Sherry\n‘,‘Alice\n‘])
Jerry
Sherry
Alice

>>> showall([‘Jerry‘,‘Sherry‘,‘Alice‘])
JerrySherryAlice

等价于下面

>>> showall = lambda x: [sys.stdout.write(line) for line in x]
>>> showall((‘I\t‘,‘Love\t‘,‘You!‘))
I       Love    You![None, None, None]

  • 例06: 在Tkinter中定义内联的callback函数

import sys
from Tkinter import Button,mainloop

x = Button(text=‘Press me‘,
           command=(lambda:sys.stdout.write(‘Hello,World\n‘)))
x.pack()
x.mainloop()

>>>

Hello,World!

Hello,World!

  • 例07: lambda和map联合使用

>>> out = lambda *x: sys.stdout.write(‘ ‘.join(map(str,x)))
>>> out(‘This‘,‘is‘,‘a‘,‘book!\n‘)
This is a book!

  • 例08: 判断字符串是否以某个字母开头

>>> print (lambda x: x.startswith(‘B‘))(‘Bob‘)
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函数一起使用,注意其参数传递
  1. >>> def sayHello():
  2. ...     title = ‘Hello, ‘
  3. ...     union = (lambda x: title + ‘‘ + x + ‘!‘)
  4. ...     return union
  5. ...
  6. >>> f = sayHello()  #此处无需带参数
  7. >>> f(‘Jerry‘)      #通过修改默认参数来传递参数
  8. ‘Hello, Jerry!‘
  • 例17. 统计Linux系统挂载点

[[email protected] ~]# 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函数效率问题

  1. import time
  2. # 测试的Def函数
  3. def square1(n):
  4. return n ** 2
  5. # 测试的Lambda函数
  6. square2 = lambda n: n ** 2
  7. print(time.time())
  8. # 使用Def函数
  9. i = 0
  10. while i < 1000000000:
  11. square1(100)
  12. i += 1
  13. print(time.time())
  14. # 使用lambda函数
  15. i = 0
  16. while i < 1000000000:
  17. square2(100)
  18. i += 1
  19. print(time.time())

输出结果:

1413272496.27
1413272703.05 (Def   函数:207s)
1413272904.49 (Lambda函数:201s)

从上面可以看出,两者的所需的时间差不多,效率丝毫不受影响.

晦涩属性:

出于简明的考虑,避免在lambda中嵌套lambda

  1. >>> action = (lambda x: (lambda y: x+ y))
  2. >>> action(99)(2)
  3. 101

像上面的例子,出于代码的简洁性考虑,最好换成下面的

  1. >>> def f(x):
  2. ...   return (lambda y: x + y)
  3. ...
  4. >>> g = f(99)
  5. >>> g(2)
  6. 101

难点例子:

from itertools import product
map(lambda p: ‘‘.join(i + j for i, j in zip(‘abcd‘, p)) + ‘e‘, product([‘.‘, ‘‘], repeat = 4))
时间: 2024-10-05 03:03:49

Python匿名函数详解的相关文章

Python 3 之 lambda匿名函数详解

------- lambda ------------------------------------- 除了def语句之外,Python还提供了一种生成函数对象的表达式形式.由于它与LISP语言中的一个工具很相似,所以称为lambda.就像def一样,这个表达式创建了一个之后能够调用的函数,但是它返回了一个函数而不是将这个函数赋值给一个变量名.这也就是lambda有时叫做匿名函数的原因.实际上,他们常常以一种行内进行函数定义的形式使用,或者用作推迟执行一些代码. lambda表达式 lambd

四、python之函数详解

一.函数 1.说白了就是把一组代码合到一起,可以实现某种功能,需要再用到这种功能的话,直接调用这个函数就行2.函数.方法是一回事3.定义一个函数的格式是:def+函数名+()4.函数必须调用了之后才能执行 eg: my_openfw = open('a.txt','a+')fw.seek(0) all_users = {} # 用来存放所有的用户名和密码def read_users(file_name):#括号里面是形式参数,其实就是一个变量 #函数体 print(file_name) with

python入门函数详解

人生苦短,我用Python,接下来我们开始数据类型的学习 当你觉得自己要放弃的时候,想想当初为什么要学习python 一:python函数入门

python 高阶函数详解。

1,概念: Iterable 和 IteratorIterable 表示该变量可以被 for in 进行迭代.Iterator 表示该变量可以被 next(o)进行迭代(上一个表示有限迭代,下一个表示一个惰性的迭代概念,可以无限迭代.)一般的Iterable 的变量有:L=[{},[],(1,),{3:4},{3,4}]for x in L:print(isinstance(x,Iterable))print(isinstance(x,Iterator)) truefalse 可见,基础变量Li

Python内置函数详解

置顶   内置函数详解 https://docs.python.org/3/library/functions.html?highlight=built#ascii 此文参考了别人整理好的东西(地址:http://www.cnblogs.com/sesshoumaru/p/6140987.html#p1),然后结合自己的理解,写下来,一方面方便自己,让自己好好学习,顺便回忆回忆:另一方面,让喜欢的盆友也参考一下. 经查询,3.6版本总共有68个内置函数,主要分类如下: 数学运算(7个) 类型转换

Python中的getattr()函数详解:

Python中的getattr()函数详解: getattr(object, name[, default]) -> value Get a named attribute from an object; getattr(x, 'y') is equivalent to x.y. When a default argument is given, it is returned when the attribute doesn't exist; without it, an exception i

python命名空间与闭包函数详解

python命名空间与闭包函数详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 本篇博客主要介绍的知识点如下: 1>.三元运算 2>.命名空间 3>.global与nonlocal 4>.函数即变量 5>.嵌套函数 6>.闭包函数 一.三元运算 1 #!/usr/bin/env python 2 #_*_coding:utf-8_*_ 3 #@author :yinzhengjie 4 #blog:http://www.cnblogs.com/yi

python基础知识~ 函数详解2

python~函数详解2 1 生成器函数   定义 如果函数有yield这个关键字,就是生成器函数.生成器函数() 获取的是生成器,不执行函数  须知 yield和return一样,都可以返回数据,但是不会彻底中断函数,分段进行函数处理  继续执行 函数(迭代器)  __next__()   __send__(参数)//和next具有同一个功能,还添加了给上一个值赋值功能  def func()  print(a)  a=yield 1 //yield特殊定义   print (b)  b=yi

Python中dict详解

yangyzh Python中dict详解 python3.0以上,print函数应为print(),不存在dict.iteritems()这个函数. 在python中写中文注释会报错,这时只要在头部加上# coding=gbk即可 #字典的添加.删除.修改操作dict = {"a" : "apple", "b" : "banana", "g" : "grape", "o&qu