• 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.   
    7. >>> L2  
    8. [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 a test"    #建此字符串按照正常情形输出
    >>> s
    'this is a test'
    >>> print s.split()           #split函数默认分割:空格,换行符,TAB
    ['this', 'is', 'a', 'test']
    >>> ' '.join(s.split())       #用join函数转一个列表为字符串
    'this is a test'

    等价于

    >>> (lambda s:' '.join(s.split()))("this is a test")
    带参数匿名函数

    >>> 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 ','Sherry ','Alice '])
    Jerry
    Sherry
    Alice

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

    等价于下面

    >>> showall = lambda x: [sys.stdout.write(line) for line in x]
    >>> showall(('I ','Love ','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 ')))
    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! ')
    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系统挂载点

    [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函数效率问题

    1. import time  
    2.   
    3. # 测试的Def函数  
    4. def square1(n):  
    5.     return n ** 2  
    6.   
    7. # 测试的Lambda函数  
    8. square2 = lambda n: n ** 2  
    9.   
    10. print(time.time())  
    11.   
    12. # 使用Def函数  
    13. i = 0  
    14. while i < 1000000000:  
    15.     square1(100)  
    16.     i += 1  
    17.   
    18. print(time.time())  
    19.   
    20. # 使用lambda函数  
    21. i = 0  
    22. while i < 1000000000:  
    23.     square2(100)  
    24.     i += 1  
    25.   
    26. 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))
  • 相关阅读:
    uva 12096
    uva 705
    uva 657
    uva 10129
    uva 816 BFS求最短路的经典问题……
    uva 1103
    uva 699
    这是昨天的内容,就这样慢慢整吧,然后,荒废了好多时间啊!!
    今天就这么乱糟糟的过啦~刚刚接触html,就稍微写了一下,明天加油,今天直接贴图
    uva 548 tree
  • 原文地址:https://www.cnblogs.com/sqz2671/p/7264305.html
Copyright © 2020-2023  润新知