前言

目录

前言

什么是列表解析式?

从循环到解析式

列表解析式:可视化解读

无条件子句的列表解析式

嵌套循环

其他解析式

还要注意可读性

列表解析式 List comprehension

带嵌套循环的列表解析式

字典解析式

总结

补充:if ... else用法


有时候,一个编程设计模式使用得十分普遍,甚至会逐步形成自己独特的语法。Python编程语言中的列表解析式(list comprehension)就是这类语法糖(syntactic sugar)的绝佳代表。

Python中的列表解析式是个伟大的发明,但是要掌握好这个语法则有些难,因为它们并是用来解决全新的问题:只是为解决已有问题提供了新的语法。

什么是列表解析式?

列表解析式是将一个列表(实际上适用于任何可迭代对象(iterable))转换成另一个列表的工具。在转换过程中,可以指定元素必须符合一定的条件,才能添加至新的列表中,这样每个元素都可以按需要进行转换。

如果你熟悉函数式编程(functional programming),你可以把列表解析式看作为结合了filter函数与map函数功能的语法糖:

>>> doubled_odds = map(lambda n: n * 2, filter(lambda n: n % 2 == 1, numbers))
>>> doubled_odds = [n * 2 for n in numbers if n % 2 == 1]

如果你不熟悉函数式编程,也不用担心:我稍后会通过for循环为大家讲解。

从循环到解析式

每个列表解析式都可以重写为for循环,但不是每个for循环都能重写为列表解析式。

掌握列表解析式使用时机的关键,在于不断练习识别那些看上去像列表解析式的问题(practice identifying problems that smell like list comprehensions)。

如果你能将自己的代码改写成类似下面这个for循环的形式,那么你也就可以将其改写为列表解析式:

:::python
new_things = []
for ITEM in old_things:if condition_based_on(ITEM):new_things.append("something with " + ITEM)

你可以将上面的for循环改写成这样的列表解析式:

:::python
new_things = ["something with " + ITEM for ITEM in old_things if condition_based_on(ITEM)]

列表解析式:可视化解读

可视化解读听上去是个不错的注意,但是我们怎么才能做到这点呢?

嘿嘿,只需要从for循环中复制粘贴,稍微调整一下就变成了列表解析式啦。

下面是我们复制粘贴的顺序:

  • 将变量赋值操作复制到新建的空列表中(第三行)
  • append()方法中的表达式参数复制到新列表中(第六行)
  • 复制for循环语句,不包括最后的:(第四行)
  • 复制if条件控制语句,同样不包括最后的:(第五行)

这样,我们将从下面这段代码:

:::python
numbers = [1, 2, 3, 4, 5]doubled_odds = []
for n in numbers:if n % 2 == 1:doubled_odds.append(n * 2)

转换成了这两行代码:

:::python
numbers = [1, 2, 3, 4, 5]doubled_odds = [n * 2 for n in numbers if n % 2 == 1]

无条件子句的列表解析式

如果是那些没有条件子句(即if SOMETHING部分)的代码呢,又该怎样复制粘贴?这些形式的代码甚至比有条件子句的代码更好实现。

一个没有if语句的for循环:

:::python
doubled_numbers = []
for n in numbers:doubled_numbers.append(n * 2)

上面这段代码页可以改写为一个列表解析式:

:::python
doubled_numbers = [n * 2 for n in numbers]

我们可以从上面那个简单的for循环中,按照这样的顺序复制粘贴:

  • 将变量赋值操作复制到新建的空列表中(第三行)
  • append()方法中的表达式参数复制到新列表中(第五行)
  • 复制for循环语句,不包括最后的:(第四行)

嵌套循环

那么嵌套循环(nested loop)又该怎样改写为列表解析式呢?

下面是一个拉平(flatten)矩阵(以列表为元素的列表)的for循环:

:::python
flattened = []
for row in matrix:for n in row:flattened.append(n)

下面这个列表解析式实现了相同的功能:

:::python
flattened = [n for row in matrix for n in row]

列表解析式中的嵌套循环读起来就有点绕口了。

注意:我本能地会想把这个列表解析式写成这样:

:::python
flattened = [n for n in row for row in matrix]

但是这行代码是错误的。这里我不小心颠倒了两个for循环的顺序。正确的代码是之前那个。

如果要在列表解析式中处理嵌套循环,请记住for循环子句的顺序与我们原来for循环的顺序是一致的

同样地原则也适用集合解析式(set comprehension)和字典解析式(dictionary comprehension)。

其他解析式

下面的代码提取单词序列中每个单词的首字母,创建了一个集合(set):

:::python
first_letters = set()
for w in words:first_letters.add(w[0])

同样的代码可以改写为集合解析式:

:::python
first_letters = {w[0] for w in words}

下面的代码将原有字典的键和值互换,从而创建了一个新的字典:

:::python
flipped = {}
for key, value in original.items():flipped[value] = key

同样的代码可以改写为字典解析式:

:::python
flipped = {value: key for key, value in original.items()}

还要注意可读性

你有没有发现上面的列表解析式读起来很困难?我经常发现,如果较长的列表解析式写成一行代码,那么阅读起来就非常困难。

不过,还好Python支持在括号和花括号之间断行。

列表解析式 List comprehension

断行前:

:::python
doubled_odds = [n * 2 for n in numbers if n % 2 == 1]

断行后:

:::python
doubled_odds = [n * 2for n in numbersif n % 2 == 1
]

带嵌套循环的列表解析式

断行前:

:::python
flattened = [n for row in matrix for n in row]

断行后:

:::python
flattened = [nfor row in matrixfor n in row
]

字典解析式

断行前:

:::python
flipped = {value: key for key, value in original.items()}

断行后:

:::python
flipped = {value: keyfor key, value in original.items()
}

请注意,我们并不是随意进行断行:我们是在每一行复制过来的代码之后断行的。

总结

纠结于写不出列表解析式吗?不要担心。先写一个for循环,能后按照本文说的顺序复制粘贴,就可以写出解析式了。

任何类似下面代码形式的for循环:

:::python
new_things = []
for ITEM in old_things:if condition_based_on(ITEM):new_things.append("something with " + ITEM)

都可以被改写为下面这种列表解析式:

:::python
new_things = ["something with " + ITEM for ITEM in old_things if condition_based_on(ITEM)]

(有删减)

原文链接:https://treyhunner.com/2015/12/python-list-comprehensions-now-in-color/

补充:if ... else用法

使用列表生成式的时候,有些童鞋经常搞不清楚if...else的用法。

例如,以下代码正常输出偶数:

>>> [x for x in range(1, 11) if x % 2 == 0]
[2, 4, 6, 8, 10]

但是,我们不能在最后的if加上else

>>> [x for x in range(1, 11) if x % 2 == 0 else 0]File "<stdin>", line 1[x for x in range(1, 11) if x % 2 == 0 else 0]^
SyntaxError: invalid syntax

这是因为跟在for后面的if是一个筛选条件,不能带else,否则如何筛选?

另一些童鞋发现把if写在for前面必须加else,否则报错:

>>> [x if x % 2 == 0 for x in range(1, 11)]File "<stdin>", line 1[x if x % 2 == 0 for x in range(1, 11)]^
SyntaxError: invalid syntax

这是因为for前面的部分是一个表达式,它必须根据x计算出一个结果。因此,考察表达式:x if x % 2 == 0,它无法根据x计算出结果,因为缺少else,必须加上else

>>> [x if x % 2 == 0 else -x for x in range(1, 11)]
[-1, 2, -3, 4, -5, 6, -7, 8, -9, 10]

上述for前面的表达式x if x % 2 == 0 else -x才能根据x计算出确定的结果。

可见,在一个列表生成式中,for前面的if ... else是表达式,而for后面的if是过滤条件,不能带else

Python列表解析式总结相关推荐

  1. python列表解析式_Python基础入门-列表解析式

    今天我们使用Python中的列表解析式来实现一些简单功能.好了关于列表解析式是什么?我的理解是它可以根据已有列表,高效创建新列表的方式.列表解析是Python迭代机制的一种应用,它常用于实现创建新的列 ...

  2. python列表解析式如何使用_python列表推导式操作解析

    python列表推导式操作解析 这篇文章主要介绍了python列表推导式操作解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 基本格式 ​[表达式 ...

  3. Python列表解析式,还支持异步?你知道吗?

    摘要 PEP-492 和 PEP-525 通过 async/await 语法,引入了对原生协程和异步生成器的支持.本 pep 提议给列表.集合.字典解析式和生成器表达式添加异步的版本. 基本原理和目标 ...

  4. python 列表解析式_python列表解析式,字典解析式,集合解析式和生成器

    一.列表解析式(列表推倒式): 功能:是提供一种方便的列表创建方法,所以,列表解析式返回的是一个列表. 1 lst = [1, 3, 5, 8, 10] 2 ll = [x+x for x in ls ...

  5. 超详细,Python列表解析式到底该怎么用?

    Python 是一种极其多样化和强大的编程语言!当需要解决一个问题时,它有着不同的方法. 在本文中,将会展示列表解析式(List Comprehension).我们将讨论如何使用它?什么时候该或不该使 ...

  6. python列表解析式如何使用_python列表解析式,生成器,及部分内建函数使用方法...

    标准库datetime 需要导入datetime模块: import datetime datetime模块: 对日期,时间,时间戳的处理 datetime的类方法 today  () now(tz= ...

  7. [python] 列表解析式的高效与简洁

    方法一(列表解析式): list1 = ["abc","efg","hij"] list2 = [i[0] for i in list1] ...

  8. Python - 列表解析式/生成器表达式

    列表解析式: [expr for iter_var in iterable if cond_expr] 生成器表达式: (expr for iter_var in iterable if cond_e ...

  9. Python进阶3——列表解析式和生成器表达式

    列表解析式相比循环更加简介易读 abc='abcdef' codes1=[] for code in abc:codes1.append(ord(code))#返回字符对应的十进制数.codes2=[ ...

最新文章

  1. jquery遍历json的几种方法
  2. GDI文字旋转90度
  3. java关闭io流_Java IO流关闭问题的深入研究
  4. VTK:相互作用之Assembly
  5. opencvsharp打开相机并视频显示
  6. asp.net web services
  7. 谷歌再次修复已遭利用的两枚高危0day (CVE-2020-16009/16010)
  8. android 自定义字体_Android自定义字体教程
  9. 【数据结构笔记】Leetcode买卖股票的最佳时机 系列总结
  10. python文字转语音的五种方式win32com,pyttsx3,百度api,可使用自己的声音
  11. 计算机思维在生活中的应用,孩子必备的计算机思维,如何从生活中培养?
  12. EasyTouch插件是否还在使用?
  13. C++ HOOK PC微信实现无限制多开,理论支持所有版本,本文使用微信 3.0.0.47
  14. android 手机性能测试工具,不服跑个分?安卓手机性能测试工具科普
  15. java程序 jnlp,使用JNLP文件启动应用程序
  16. dellr740服务器智能风扇开启,Dell PowerEdge R740 机架式服务器,配置磁盘阵列的方法...
  17. linux卸载nginx(更新)
  18. windows环境下设置多个PHP版本的环境变量
  19. 使用Openoffice实现并发多进程word文档转换预览
  20. 《高等统计物理学》Cookbook(持续更新)

热门文章

  1. 开源MyBatis分页插件,省时省力
  2. 这款可视化工具,Java 调优起来真的 so easy啊
  3. 如果MySQL引起CPU消耗过大,你会怎么优化?
  4. 疫情之下!国内互联网公司上班时间汇总!
  5. 辽宁师范大学计算机科学与技术在哪个校区,辽宁师范大学有几个校区及校区地址 哪个校区最好...
  6. [WinError 17] 系统无法将文件移到不同的磁盘驱动器
  7. 如何动态调试Python的第三方库
  8. jupyter notebook 更改工作目录
  9. activity重启问题
  10. idea main java.lang.ClassNotFoundException