[Python学习日记-41] Python 中的列表生成式
[Python学习日记-41] Python 中的列表生成式
简介
什么是列表生成式
简介
列表是编程当中最为常用的一种数据类型,同时我们也会经常操作(增删改查)里面的数据,有的时候我们会需要大批量的修改所有列表当中的数据,本篇所讲的列表生成式就是为了应对这一状况的,下面我们来看看到底什么是列表生成式吧。
什么是列表生成式
假设现在有个需求,现有列表 a = [0,1,2,3,4,5,6,7,8,9],要求你把列表里的每个值都加1,你会怎么实现呢?你可能会想到两种方式。
一、初窥门道版
先看一下初窥门道版所写的代码吧,代码如下
a = [0,1,2,3,4,5,6,7,8,9]
b = []
for i in a:
b.append(i+1)
print(b)
a = b
代码输出如下:
从输出来看,这的确是实现了我们所要求的功能,但是中间过程生成了一个新列表 b,并且还需要遍历列表 a,在遍历过程中把 a 的每一个值加1之后存入 b 里面,最后把 b 赋值给 a,这样的做法说他只是初窥门道并无道理,其生成了新的列表浪费了宝贵的内存空间,假设如果里面的数据有上亿的话,这一个加1的过程会需要两倍的内存空间。如果我们把服务器搭建在云环境当中,这样的资源浪费就相当于在浪费白花花的钞票,所以这样的代码优化空间还是非常大的。
二、略有所成版
下面来看看略有所成版的代码,代码如下
a = [0,1,2,3,4,5,6,7,8,9]
for index,i in enumerate(a):
a[index] += 1
print(a)
代码输出如下:
该代码用 enumerate() 函数把列表中的下标和元素都分别赋值给了 index 和 i,for 循环当中实现了一边遍历 a 列表,一边对 a 列表当前的元素进行加1操作,我们只需要修改一下代码就可以看到它的操作过程,代码如下
a = [0,1,2,3,4,5,6,7,8,9]
for index,i in enumerate(a):
a[index] += 1
print(a)
代码输出如下:
而从输出来看,略有所成版也是实现了我们所要求的功能,并且优化了初窥门道版中的内存占用空间过高的问题,但是这个解决方案只能算作中规中矩了,并没有特别大的新意,这并不符合我们一个高端程序员的定位,那我们来看看下面的登峰造极版吧。
三、登堂入室版
下面来看看登堂入室版的代码,代码如下
a = [0,1,2,3,4,5,6,7,8,9]
a = map(lambda x:x+1, a)
a = list(a)
print(a)
代码输出如下:
该代码使用了 map() 函数,之前讲匿名函数和内置函数的时候介绍过 map() 那时候说该函数是可以把后面的列表里的每一个元素扔进去函数当中运算,然后在返回回来组合在一起进行输出,最后我们只需要再把 map() 函数输出的数据进行转换成列表就好了。虽然这一版本的代码比之前的代码简介太多了,也更加接近高端程序员的标准了,但是总感觉还差一点,那我们看看最后一个登峰造极版吧。
四、登峰造极版
下面来看看登峰造极版的代码,代码如下
a = [0,1,2,3,4,5,6,7,8,9]
a = [i+1 for i in a]
print(a)
代码输出如下:
在上面的代码中所呈现的写法就叫做列表生成式,英文名叫 List Comprehension 是一种简洁的语法,用于快速生成列表。它的基本语法如下
[expression for item in iterable if condition]
列表生成式会对可迭代对象中的每个元素进行表达式的计算,并根据条件表达式进行过滤。下面给出一些其他列表生成式的例子,代码如下
1、生成一个包含1到10的平方数的列表:
squares = [x**2 for x in range(1, 11)]
print(squares)
代码输出如下:
2、生成一个只包含偶数的列表:
evens = [x for x in range(1, 11) if x % 2 == 0]
print(evens)
代码输出如下:
3、生成一个包含两个列表的元组的列表:
pairs = [(x, y) for x in [1, 2, 3] for y in ['a', 'b', 'c']]
print(pairs)
代码输出如下:
4、过滤一个字符串中的元音字母:
vowels = [x for x in 'hello' if x in 'aeiou']
print(vowels)
代码输出如下:
5、过滤一个列表中的负数:
positive_nums = [x for x in [-1, 2, -3, 4, -5] if x > 0]
print(positive_nums)
代码输出如下:
有的同学就会下意识的觉得,这个列表生成式怎么感觉和三元运算有点相似啊,是的非常相似,不过也不完全一样,三元运算是判断的结果如果是 True 的话执行 if 前面的,如果是 False 的话执行后面的,而列表生成式可以看作是三元运算的循环版,有的同学会问这样写有什么作用吗?其实没什么大用,但是我们毕竟是高端程序员,那我们肯定要用符合我们身份的代码,所以说以后遇到适用列表生成式的状况时记得用起来。
总之,列表生成式可以大大简化代码,并提升可读性。但在处理大量数据时,列表生成式可能会占用较多的内存,此时可以考虑使用生成器表达式或者迭代器来替代列表生成式。
作者:JoveZou