Python之列表表达式及高阶函数lamda、zip、enumerate、map和filter方法

本文介绍了Python中列表表达式(List Comprehension)的高效操作,如元素倍增、交集计算;展示了lambda匿名函数的简洁用法,以及zip、enumerate、map、reduce和filter函数在数据处理中的应用。通过实例演示,帮助理解如何利用这些工具简化编程任务。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、列表表达式[List Comprehension]

  • 顾名思义,这个表达式作用是以一个快捷的方法对列表进行操作或运算,返回新的列表。其使用方式为[表达式 for 变量 in 列表] 或者 [表达式 for 变量 in 列表 if 条件]。
  • 一个最简单的列表表达式,如下所示:
>>> list1 = [1, 2, 3, 4]
>>> list2 = [i*i for i in list1]
>>> list3 = [i*i for i in list1 if i>2]
>>> print(list2)
[1, 4, 9, 16]
>>> print(list3)
[9, 16]
  • 列表表达式也可以遍历元组生成新的列表(如 list5),然而却不能直接生成新的元组。比如 list6 实际上是个生成器表达式,不属于列表表达式了。对于生成器表达式可以通过使用 list6.next() 方法一次一次取值。
>>> tuple1 = (1, 2, 3, 4)
>>> list5 = [i*i for i in tuple1]
>>> print(list5)
[1, 4, 9, 16]
>>> list6 = (i*i for i in tuple1)
>>> print(list6)
<generator object <genexpr> at 0x03559E10>
  • 统计字符串列表中每个字符串的长度:
>>> words = ['abc','defg','I love python', 'Django']
>>> len_list = [ len(word) for word in words ]
>>> print(len_list)
[3, 4, 13, 6]
  • 利于列表表达式求两个列表的交集:
>>> a = [ 3, 5, 6, 8]
>>> b = [ 5, 6]
>>> a_b = [ i for i in a if i in b]
>>> print(a_b)
[5, 6]
  • 打印出 100 以内所有十位数比个位数大 1 位的数字:
>>> num = [ n1*10+n2 for n1 in range(0, 10) 
        for n2 in range(0, 10) if n1 == n2+1 ]
>>> print(num)
[10, 21, 32, 43, 54, 65, 76, 87, 98]

二、匿名函数 lambda 函数

  • Lambda 函数又称匿名函数,也有人称为 lambda 表达式。顾名思义,匿名函数就是没有名字的函数。函数没有名字也行吗?当然可以啦。有些函数如果只是临时一用,而且它的业务逻辑也很简单时,就没必要非给它取个名字不可。
  • lambda 匿名函数的格式是 lambda 参数: 表达式,冒号前是参数,可以有多个,用逗号隔开,冒号右边的为表达式。其实 lambda 返回值是一个函数的地址,也就是函数对象。
  • 如下所示,是一个最简单的 lambda 函数:
>>> add = lambda x, y: x+y
>>> type(add)
<class 'function'>
>>> print(add(3,5))
8
  • 既然是匿名函数,为什么还要给它取个叫 add 的名字?这的确是多次一举。其实 lambda 最常用的还是和 sorted, map、reduce、filter 这些高级函数结合使用。
  • 再来看两个使用 lambda 函数结合 sorted 方法排序的经典例子:一个按绝对值大小排序,一个按字符串长度排序:
>>> list1 = [ 5, -3, 1, 8, -4 ]
>>> list2 = sorted(list1, key=lambda x:abs(x))
>>> print(list2)
[1, -3, -4, 5, 8]

>>> list3 = ['to', 'python', 'ABC']
>>> list4 = sorted(list3, key=lambda x:len(x))
>>> print(list4)
['to', 'ABC', 'python']
  • 如下所示,是一道关于 lambda 函数的经典面试题,flist[0] 结果输出什么呢?
>>> flist = [ lambda x:x*x for x in range(1, 3)]
>>> print(flist)
[<function <listcomp>.<lambda> at 0x03ADE2B8>, <function <listcomp>.<lambda> at 0x03ADE300>]
>>> flist[0]
<function <listcomp>.<lambda> at 0x03ADE2B8>
>>> flist[0](2)
4
  • 这个主要考函数对象列表,千万不要和列表表达式搞混了,答案是 flist[0] 输出的是函数对象。

三、zip 函数

  • zip() 函数来可以把 2 个或多个列表合并,并创建一个元组对的列表,元组对的数量以合并列表的最短长度为准
  • python 3中 zip 方法合并列表后生成的是 zip 对象,使用 list 方法可以将其变成列表,使用 dict 方法可以将其变成字典:
>>> l1 = [ 1, 2, 3 ]
>>> l2 = [ 'x', 'y', 'z']
>>> l3 = [ 'x', 'y' ]
>>> zip(l1, l2)
<zip object at 0x031D6828>
>>> print(list(zip(l1, l2)))
[(1, 'x'), (2, 'y'), (3, 'z')]
>>> print(list(zip(l1, l3)))
[(1, 'x'), (2, 'y')]
>>> print(dict(zip(l1,l3)))
{1: 'x', 2: 'y'}
  • 实际上 zip 方法支持所有可迭代对象(字符串、列表、元祖、字典),而不仅仅是列表。利用这个特性,可以很容易创建各种字典,包括很复杂的字典。
  • 来看 2 个经典例子,如下所示,注意 zip 对象支持直接遍历,不需要先转成 list 或 dict:
>> > l1 = [1, 2, 3]
>> > str1 = "abc"
>> > print(dict(zip(l1, str1)))
{1: 'a', 2: 'b', 3: 'c'}
>> > name = ["John", "Jim", "Lucy"]
>> > year = [1983, 1985, 1995]
>> > birth_year = dict(zip(name, year))
>> > print(birth_year)
{'John': 1983, 'Jim': 1985, 'Lucy': 1995}
>> > for name, year in zip(name, year):
    print("{} - {}".format(name, year))

John - 1983
Jim - 1985
Lucy - 1995
  • 利用 zip(*some_list) 方法可以实现元组列表的反向解压,如下所示:
>>> l1 = [("John", 1995), ("Lucy", 2000), ("Max", 1985)]
>>> name, year = zip(*l1)
>>> print(name)
('John', 'Lucy', 'Max')
>>> print(year)
(1995, 2000, 1985)
>>> l2 = dict(l1)
>>> print(l2)
{'John': 1995, 'Lucy': 2000, 'Max': 1985}
>>> name1, year1 = zip(*l2)
Traceback (most recent call last):
  File "<pyshell#6>", line 1, in <module>
    name1, year1 = zip(*l2)
ValueError: too many values to unpack (expected 2)
  • 注意 unzip 只支持元组列表,不支持 dict 直接解压。

四、enumerate() 函数

  • enumerate() 函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标,常见用于 for 循环。一般只有需要同时用到索引 index 和 value 值的时候才用 enumerate 方法。
  • 直接使用 enumerate 方法生成是个 enumerate 对象,可以遍历。
>> > name = ["John", "Lucy", "Mary"]
>> > name1 = enumerate(name)
>> > print(name1)
< enumerate object at 0x030D0FA8 >
>> > for index, name in enumerate(name):
    print("{}-{}".format(index, name))

0 - John
1 - Lucy
2 - Mary

五、map 函数

  • map 函数是个非常有用的方法,其语法是 map(function, iterable, …)。map 方法可以接收函数作为参数,并将其映射于列表的多个元素。
  • Python 2 中返回列表,Python 3 中返回迭代器,需要使用 list 方法再生成列表。
  • map 函数不仅支持自定义的函数和 lambda 函数,还支持 Python 自带的函数。
  • 如下所示,map 函数应用,将计算平方的 lambda 函数映射于列表中的每个元素:
>>> l = map(lambda x: x ** 2, [1, 2, 3, 4, 5])
>>> print(l)
<map object at 0x03553790>
>>> print(list(l))
[1, 4, 9, 16, 25]
  • map 函数还支持多个列表的映射和计算,如下所示:
>>> l1 = [1, 2, 3]
>>> l2 = [4, 5, 6, 7]
>>> l3 = [8, 9]
>>> print(list(map(lambda x,y,z:x+y+z, l1, l2, l3)))
[13, 16]
  • lambda 函数中的 x, y, z 分别对应列表 l1、l2 和 l3 中的元素,计算后的生成的列表长度取决于各个列表的最短长度。
  • 下面来看一道关于 map 函数的经典考题:有两个字符串 A 和 B,现在要统计字符串 A 中有多少个字符也在字符串 B 中可以找到,常规函数解法如下:
>>> strA = "aAAAbBCC"
>>> strB = "aA"
>>> def count1(str1, str2):
   a = 0
   for c in str1:
      if c in str2:
         a += 1
   return a

>>> count1(strA, strB)
4
  • 使用 map 函数经典解法如下:
>>> strA = "aAAAbBCC"
>>> strB = "aA"
>>> print(sum(map(strA.count, strB)))
4
  • 来分析下上面这段代码,Python 自带的 string.count(char) 函数的作用是统计一个字符串 string 含有字符 char 的数量,在本例中 strB 相当于 char 的一个参数列表 [“a”, “A”],map 函数先统计 strA 中字符 a 的数量,再统计 strA 中字符 A 的数量,获得列表 [1, 3],然后将它们相加,即可获得字符串 A 中总共有多少字符可以在 B 中找到。

六、reduce 函数

  • reduce() 函数会对参数序列中元素进行累积,该方法第一个参数必需是函数,而且传入的函数必需要有 2。个参数,否则出现错误。该方法将一个数据集合(列表,元组等)中的所有数据进行下列操作:用传给 reduce 中的函数 function 先对集合中的第 1、2 个元素进行操作,得到的结果再与第三个数据用 function 函数运算,最后得到一个结果。
  • reduce 函数很适合连续计算(比如列表求和或连乘计算阶乘),经典代码如下:
>>> from functools import reduce
>>> reduce(lambda x, y: x+y, [1,2,3,4,5])
15
>>> reduce(lambda x,y:x*y,range(1,5))
24
  • Python 3 中 reduce() 函数已经被从全局名字空间里移除了,它现在被放置在 fucntools 模块里,如果想要使用它,则需要通过引入 functools 模块来调用 reduce() 函数。

七、filter 函数

  • Python 的 filter() 函数用于过滤序列,过滤掉不符合条件的元素,返回由符合条件元素组成的新列表。该方法与 map 和 reduce 类似,第一个参数都是函数,作用于可以迭代的对象比如列表和元组,但不同的是 filter 方法传入的函数是判断性函数,只有符合条件的列表元素才会加入新的列表。Python 2 中返回列表,Python 3 中返回 filter 对象,使用 list 方法可以转化为列表。
  • 如下所示,使用 filter 方法打印出 10 以内偶数,只有满足 x % 2 == 0 的列表元素才会加入新的列表:
>>> l = filter(lambda x: x % 2 == 0, range(10))
>>> print(l)
<filter object at 0x02C0BBF0>
>>> print(list(l))
[0, 2, 4, 6, 8]
  • 利用 filter 方法删除字符串列表里的空白字符串,只有满足 s and s.strip() = True 的字符串才会加入新的列表:
def not_empty(s):
    return s and s.strip()

list(filter(not_empty, ['A', '', 'B', None, 'C', '  ']))
# 结果: ['A', 'B', 'C']
  • 如下所示,是一道关于 filter 方法的经典面试题,利用 filter 方法筛选出一个列表中的素数:
>>> import math
>>> def isPrime(n):
       if n <= 1:
          return False
       elif n == 2:
          return True
       else:
          for i in range(2, int(math.sqrt(n))+1):
             if n%i == 0:
                return False
          return True

>>> l1 = [-1, 0, 2, 3, 6, 7, 8]
>>> l2 = list(filter(isPrime, l1))
>>> print(l2)
[2, 3, 7]
<think>根据用户的上一次问题,用户希望了解Pythonlambda表达式的用法或语法。结合用户指令中的要求:生成相关问题、使用中文回答、正确格式化数学公式(但当前主题不涉及数学公式)。从引用的内容来看:[^1]:介绍了Lambda表达式是什么,语法规则,例子,以及在高阶函数中的应用。[^2]:强调lambda是一个表达式,可以出现在def不能出现的地方,比如列表常量或函数调用的参数中。[^3]:详细说明了Lambda表达式的语法结构,并提供了示例。我的回答将包括:1.Lambda表达式的基本概念(是什么)。2.语法规则(怎么写)。3.常规函数的区别(特别是作为表达式的特点)。4.常见的使用场景示例(包括高阶函数中的使用)。5.优势限制。同时,我会在最后生成相关问题。注意:回答中引用部分要自然地添加引用标识。由于主题是编程,不需要使用数学公式,所以不会出现行内或独立数学公式。但是,如果引用中包含数学公式,我会按照指令处理(但当前引用内容没有数学公式)。回答结构:1.什么是Lambda表达式?2.Lambda表达式的语法规则3.Lambda表达式的特点4.Lambda表达式的常见使用示例5.Lambda表达式的优势限制6.生成相关问题</think> ### Python Lambda 表达式详解 #### 1. 什么是 Lambda 表达式Lambda 表达式Python 中创建小型匿名函数的快捷方式,不需要使用 `def` 关键字定义完整函数。它是一种特殊的函数表达式,可以出现在常规函数无法出现的位置(如列表常量或函数参数中)[^1]。 #### 2. 基础语法规则 `lambda arguments: expression` - **arguments**:函数参数,多个参数用逗号分隔 - **expression**:函数逻辑,表达式结果即为返回值 - **特征**:单行表达式,不支持代码块或多行语句[^2] #### 3. 核心特性 1. **匿名性**:无需函数名 2. **表达式属性**:可嵌入复杂表达式 3. **精简性**:简化函数封装 4. **闭包支持**:访问封闭作用域的变量 #### 4. 常用示例场景 ```python # 基础运算 平方计算 = lambda x: x ** 2 print(平方计算(5)) # 输出 25 # 多参数函数 加法运算 = lambda a, b: a + b print(加法运算(3, 7)) # 输出 10 # 高阶函数应用(map/filter) 数字列表 = [1, 3, 5, 7] 平方列表 = list(map(lambda x: x*x, 数字列表)) # [1, 9, 25, 49] 过滤奇数 = list(filter(lambda x: x%2==0, 数字列表)) # [ ] # 排序应用 用户数据 = [('Alice', 32), ('Bob', 25)] 按年龄排序 = sorted(用户数据, key=lambda x: x[1]) # [('Bob',25), ('Alice',32)] ``` #### 5. 普通函数对比 | 特性 | Lambda 表达式 | def 函数 | |--------------|----------------------------|---------------------| | 函数名 | 匿名 | 需明确命名 | | 代码结构 | 单行表达式 | 支持多行代码块 | | 作用域 | 继承外围作用域 | 独立作用域 | | 适用场景 | 简单逻辑/参数传递 | 复杂逻辑 | #### 6. 使用限制 1. **表达式限制**:只能包含单条表达式,不支持多行语句 2. **可读性下降**:复杂逻辑会降低代码可读性 3. **调试困难**:堆栈跟踪显示为 `<lambda>`,增加调试难度 4. **功能局限**:不支持文档字符串(docstrings)[^3]
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

╰つ栺尖篴夢ゞ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值