0%

18、匿名函数.md

一、lambda表达式(匿名函数)

1、概念

lambda函数也叫匿名函数,即,函数没有具体的名称

1
2
3
4
5
6
7
8
def multip(x):  
return x * 2

lam = lambda x : x * 2

print(multip(2))
print(lam(2))

运行完成之后的结果都是4,通过结果我们可以知道,lambda在Python这种动态的语言中确实没有起到什么特别大的作用,因为有很多别的方法能够代替lambda,所以python对 ambda有比较简单有限的支持

简单来说好比电影里面的群众演员,往往他们的戏份很少,最多是衬托主演,跑跑龙套(出来就死的那种),他们需要名字吗?不需要,因为他们仅仅只是临时出镜,下次可能就用不着了,所以犯不着费心思给他们每个人编个号取个名字,毕竟取个优雅的名字是很费劲的事情

2、为什么要使用lambda

通过上面的代码,我们会发现

  1. lambda简化了函数定义的书写形式。是代码更为简洁,但是使用函数的定义方式更为直观,易理解。

  2. 对于一些抽象的,不会别的地方再复用的函数,有时候给函数起个名字也是个难题,使用lambda不需要考虑命名的问题

3、语法格式

  1. 语法

    1
    lambda 形参列表 : 表达式
  2. 语法说明

    1. 关键字lambda后面紧跟着形参列表. 注意形参列表不能用圆括号括起来
    2. 形参列表后面紧跟着一个冒号(:)
    3. 冒号后面是唯一的表达式. 注意:此表达式必须是合法的表达式.
    4. lambda会自动返回表达式的运算结果
  3. 注意事项

    1. lambda 表达式只是对简单到只有一行代码的函数的语法糖(简写), 如果有多行代码, 则无法使用 lambda 表达式
    2. lambda 函数可以接收任意多个参数 (包括可选参数) 并且返回单个表达式的值
    3. lambda用来编写简单的函数,而def用来处理更强大的任务

4、示例代码

  1. 无参

    1
    2
    3
    4
    5
    #函数名为fun
    def fun():
    return Ture
    #无参数 无函数名
    lambda : Ture
  2. 位置参数

    1
    2
    m = lambda x,y,z: x*y*z
    print(m(2,3,4))
  3. 关键字参数

    1
    2
    3
    4
    5
    6
    #函数
    def add(x,y=2)
    return x + y
    #lambda表达式
    add = lambda x,y=2: x+y
    print(add(10))
  4. 不定长参数,返回元组

    1
    2
    3
    4
    5
    6
    7
    8
    9
    #函数定义
    def fun(*args):
    return args
    #表达式
    a = lambda *z: z * 2

    if __name__ == '__main__':
    print(a(1, 2, 3, 4, '姓名'))

  5. 不定长参数,返回字典

    1
    2
    3
    4
    5
    6
    7
    8
    # 函数
    def fun_kwargs(**kwargs):
    return kwargs
    # 表达式
    c = lambda **kwargs: kwargs

    if __name__ == '__main__':
    print(c(arg1=1, arg2=1, arg3='姓名'))
  6. 直接后面传递实参

    1
    2
    3
    if __name__ == '__main__':
    print((lambda x, y: x if x > y else y)(100, 200))
    print((lambda x: x ** 10)(2))
  7. 配合函数使用

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    def say(name, content):
    return (lambda name, content: name + 'say: ' + content)(name, content)

    if __name__ == '__main__':
    print(say('小明', 'Hello World'))


    def action(x):
    return lambda y: x+y

    fun = action(2)
    print(f(3))
  8. 使用在不能定义函数的

    1
    2
    info = [(lambda a: a**3)(1), (lambda b: b**3)(2)]
    print(info)

5、小结

  1. 对于单行函数,使用lambda可以省去定义函数的过程,让代码更加精简。
  1. 在非多次调用的函数的情况下,lambda表达式即用既得,提高性能
  2. 如果可以使用for…in…if来完成的,坚决不用lambda。
  3. 如果使用lambda,lambda内不要包含循环,如果有,我宁愿定义函数来完成,使代码获得可重用性和更好的可读性。lambda 是为了减少单行函数的定义而存在的。
  1. lambda的主体是一个表达式,而不是一个代码块。仅仅能在lambda表达式中封装有限的逻辑进去。
  2. lambda表达式是起到一个函数速写的作用。允许在代码内嵌入一个函数的定义。

二、内置函数

1、map

1.1、说明

对一个及多个可迭代对象执行同一个操作,返回一个map对象(可迭代对象)

1.2、语法格式

1
map(func, *iterables)

1.3、参数说明

  • func:

    函数名,不能为None 也可以是匿名函数

  • iterables:

    一个或者多个可迭代的对象,例如:list 字典

1.4、原理图

1.5、返回值

Python 3.x 返回map对象(迭代器)

Python 2.x 返回列表

1.6、注意

返回一个新的迭代对象,不会对原来的序列有影响,输出的时候注意因为是一个迭代对象,所有想查看结果可以通过for循环或者list()来显示

1.7、举个栗子

  • 基本使用

    1
    2
    li = [1, 2, 3, 4, 5]
    iter1 = map(lambda x: x * 2, [1, 2, 3, 4, 5])
  • 元组和列表配合使用

    1
    2
    3
    #注意 传入两个可迭代对象,所以传入的函数必须能接收2个参数
    iter2 = map(lambda x, y: x + y, [1, 2, 3, 4], (10, 20, 30, 40))
    print(tuple(iter2))
  • 当传入多个可迭代对象时,且它们元素长度不一致时,生成的迭代器只到最短长度

    1
    2
    3
    iter3 = map(lambda x, y: x + y if y else x + 10, [1, 2, 3, 4, 5], (1, 2, 3, 4))
    print(tuple(iter3))
    # 输出(2, 4, 6, 8)
  • 结合函数使用

    1
    2
    3
    4
    5
    nums = [1, 2, 3, 4, 5, 6, 7, 8, 9]
    def fun(x):
    return x * x

    print(list(map(fun, nums)))

2、filter

2.1、说明

对于序列中的元素进行筛选,最终获取符合条件的序列,相当于一个迭代器,调用一个布尔函数func来迭代seq中的每个元素,返回一个是bool_seq返回为True的序列

2.2、语法格式

1
filter(function, iterable)

2.3、参数说明

  • function:

    函数或None

  • iterable:

    可迭代对象,例如: 列表 字典,集合 字符串等

2.4、返回值

  • 如果参数为function,那么返回条件为真的返回迭代器对象
  • 如果参数为None的话,那么返回序列中所有为True的元素

2.5、原理图

2.6、举个栗子

  • 要过滤掉所有值为False的列表

    1
    2
    li = [1, 0, 0.0, None, {}]
    filter(None, [-2, 0, 2, '', {}, ()])
  • 过滤字母(字符串)

    1
    filter(lambda x: x !='a','abcd')
  • 过滤元素(列表)

    1
    2
    names = ['老宋', '老王', '小张', '小花', '小明', '']
    filter(None, names)
  • 过滤列表中的奇数

    1
    2
    3
    nums = [0,101,10,7,3,5,8,131,88] 
    if __name__ == '__main__':
    filter(lambda x: x%2, nums)
  • 将2-10间所有质数列出来

    1
    2
    if __name__ == '__main__':
    filter(lambda x: not [x for i in range(2,x) if x%i == 0],range(2,10))
  • 过滤所有子列表中,元素是’Iphone’ [示例代码有问题]

    1
    2
    3
    4
    5
    6
    7
    def filter_shop(shop):  
    if shop:
    return shop != 'Iphone'
    else:
    return False
    shops = [['huawei', 'Iphone', 'xiaomi'], ['Iphone', 'meizu','vivo']]
    filter(fitler_shop(shop)) for shop in shops
  • 过滤文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    #需要的模块  
    import os
    #列出需要查找的目录的所有文件

    files = os.listdir('D:\googleDownload')

    a = filter(lambda file: file.endswith('gz'), files)
    for i in a:
    print(i)

    ------ 改正后代码
    def filter_shop(shop):
    if shop != 'Iphone':
    return shop

    else:
    return False

    shops = [['huawei', 'Iphone', 'xiaomi'], ['Iphone', 'meizu', 'vivo'], ['meizu']]
    for items in shops:
    for item2 in items:
    a = filter_shop(item2)
    # a = (a != "False" and a )
    print(a)

  • 底层实现

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    def filter1(func,seq):
    # 建一个空序列,用于存储过滤后的元素
    f_seq = []
    #对序列中的每个元素进行迭代
    for item in seq:
    #如果为真的话
    if func(item):
    #满足条件者,则加入
    f_seq.append(item)
    # 返回过滤后的元素
    return f_seq
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    代码测试

    li = ['tiger', 'five', 'qf', 'f803']


    def fi(test):
    if test != 'tiger':
    return test


    a = filter1(fi, li)
    for i in a:
    print(i)

3、reduce

3.1、说明

reduce函数会对参数序列中元素进行累积。

在Python 3里,reduce()函数已经被从全局名字空间里移除了,它现在被放置在fucntools模块里 用的话要先引入。

3.2、语法

1
reduce(function, sequence, initial=None)

3.3、参数说明

  • function

    处理序列的函数

  • sequence

    序列对象

  • initial

    可选参数第一次调用的参数

3.4、返回值

函数处理过的对象

3.5、备注

function有三个参数,

reduce依次从sequence中取一个元素,和上一次调用function的结果做参数再次调用function。

第一次调用function时,如果提供initial参数,会以sequence中的第一个元素和initial作为参数调用function,

否则会以序列sequence中的前两个元素做参数调用function

3.6、举个栗子

  • 对字符串的处理

    1
    2
    3
    value1 = reduce(lambda x, y: x + y,['hello', 'word'])
    if __name__ == '__main__':
    print(value1)
  • 两个参数的数字类型处理

    1
    2
    3
    value2 = reduce(lambda x, y: x * y, [1, 2, 3, 4])
    if __name__ == '__main__':
    print(value2)
  • func()函数不能为None,否则报错

    1
    2
    3
    4
    5
    6
    7
    print(reduce(None,[1,2,3,4]))
    """
    Traceback (most recent call last):
    File "/Users/zhangwei/work/PycharmProjects/Demo/day05/src/lambda_reduce.py", line 12, in <module>
    print(reduce(None,[1,2,3,4]) )
    TypeError: 'NoneType' object is not callable
    """
  • func(x,y)只能有两个参数,否则报错

    1
    2
    3
    4
    5
    6
    7
    8
    print(reduce(lambda x: x * 2, [1, 2, 3, 4], 10))

    """
    Traceback (most recent call last):
    File "/Users/zhangwei/work/PycharmProjects/Demo/day05/src/lambda_reduce.py", line 12, in <module>
    print(reduce(lambda x: x * 2, [1, 2, 3, 4], 10))
    TypeError: <lambda>() takes 1 positional argument but 2 were given
    """
  • 底层实现

    1
    2
    3
    4
    5
    6
    7
    8
    9
    def reduce(function, iterable, initializer=None):
    it = iter(iterable)
    if initializer is None:
    value = next(it)
    else:
    value = initializer
    for element in it:
    value = function(value, element)
    return value