前言:
Python使用缩进来标识语句块, 来表明代码之间的逻辑层级关系, 有的时候一些简单的代码逻辑,确写了好几行, 看起来既不简洁也不优雅.
其实Python提供了更贴近自然语言的语法, 从而写出更高可读性的代码. 本文介绍一下列表表达式
1.列表表达式
一个场景, 需要返回一个列表为0~19中奇数的数据的平方.
1.1 ☹️丑陋的写法 for循环
使用for循环来实现, 需要3步:
- 定义一个空列表
- 遍历0-19元素, 判断是否为奇数
- 将满足的数据求平方, 附加到列表末尾
代码如下:
In [1]: squares = []
In [2]: for i in range(20):
...: if i%2:
...: squares.append(i * i)
In [3]: squares
Out[3]: [1, 9, 25, 49, 81, 121, 169, 225, 289, 361]
1.2 🙂使用map 和 filter
map() 和 filter() 是基于函数式编程(相关文章)的替代方法, 可以将代码压缩到1行, 缺点是牺牲了可读性.
In [4]: list(map(lambda i: i*i , filter(lambda j: j%2, range(20))))
Out[4]: [1, 9, 25, 49, 81, 121, 169, 225, 289, 361]
1.3 😃列表表达式
一种更加优雅的实现方式是使用列表表达式. 可以将for循环应用到列表的初始化过程中.
语法如下
[ <expr> for <member> in <iterable> if <condition> ]
其中 for member in iterable 对数据进行遍历, if condition 语句完成判断筛选, expr来执行运算生成结果. 代码如下:
In [5]: [i*i for i in range(20) if i%2]
Out[5]: [1, 9, 25, 49, 81, 121, 169, 225, 289, 361]
使用列表表达式的写法, 更加贴近自然语言的语法, 更加便于理解.
1.3.1 应用到字典和集合
列表表达式, 两边的操作符换为 { } , 返回的结果就是一个集合
In [6]: {s for s in 'some string' if s.isalpha()}
Out[6]: {'e', 'g', 'i', 'm', 'n', 'o', 'r', 's', 't'}
若数据为 key: value 格式, 返回就是一个字典
In [7]: code = [('Red', 'FF0000'), ('Yellow', 'FFFF00'), ('Black', '000000')]
In [8]: {k: '#'+v for k, v in code}
Out[8]: {'Red': '#FF0000', 'Yellow': '#FFFF00', 'Black': '#000000'}
2. 什么时候不用列表表达式
2.1 多层嵌套
尽管列表表达式支持多层for循环嵌套, 但是这样带来的结果,可能会使您的代码更加混乱难以阅读, 所以尽量不要使用超过一层的嵌套.
下面是一个不好的示范
In [9]: result = [(x, y) for x in range(10) for y in range(5) if x * y > 10]
2.2 超大数据
列表表达式和map的区别是, 列表表达式直接返回一个列表, 而map返回一个生成器, 所以在面对大量数据时map有更好的性能表现, 因为map可以保持较小的内存占用.
In [10]: timeit(lambda: sum([i * i for i in range(100_000_000)]), number=1)
Out[10]: 16.525786700000026
In [11]: timeit(lambda: sum(map(lambda i: i*i, range(100_000_000))), number=1)
Out[11]: 14.82606560000022
总结:
便利可迭代对象生成新的数据时, 优先考虑使用列表表达式