列表生成器为创建列表提供了一种简洁的方式。其语法为
li = [f(var) for var in iterable if condition]
f(var)
为变量var
的表达式,f(var)
为最终列表里每个结果的值
iterable
为可遍历的数据结构,condition
则为条件判断(condition
也可没有)
当然还可以有多个变量var
, 即可以有同时var1, var2, var3
,也可以有多层for和多个判断if
我们通过例子深刻理解
比如说,我们可以将一个for循环变成列表用列表生成器的方式实现,简洁地实现一个平方数列表
Copysquares=[x**2 for x in range(10)]
# [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
# 其等效于
Copysquares = []
for x in range(10):
Copysquares.append(x**2)
我们还可以在列表生成器中加入if语句
下列例子的功能是实现字符串分割且去除空格
s = 'hello world'
comp = [x for x in s if x != ' ']
# ['h','e','l','l','o','w','o','r','l','d']
# 其等效于
comp = []
for x in s:
if x != ' ':
comp.append(x)
当然我们还可以更复杂,使用两个for循环以及if判断
两个0-4范围内数,其中必须一个为偶数,另一个为奇数,返回相加的所有结果
add_ =
[i+j for i in range(5) if i % 2 == 0 for j in range(5) if j % 2 == 1]
# [1, 3, 3, 5, 5, 7]
# 其等效于
add_ = []
for i in range(5):
if i % 2 == 0: # 当i为偶数时即0,2,4
for j in range(5):
if j % 2 == 1: # 当j奇数时即1,3
add_.append(i+j)
# 计算顺序为 0+1,0+3,2+1,2+3,4+1,4+3
# 即[1, 3, 3, 5, 5, 7]
可以看到其实写列表生成器就像正常在写循环语句一样,主要区别有两个:
实际上,列表生成式这个概念在Python中被泛化了。不但可以生成列表,还可以生成字典 dict 和集合 set。
字典生成器的语法为
dic = {key:value for key,value in iterable}
举例,将元组转换为dic
tup = [('zhang',0),('liu',1),('lan',2)]
dic = {k:v for k,v in tup}
print(dic)
# {'zhang': 0, 'liu': 1, 'lan': 2}
其实对于上面这个简单的例子,可以不用字典生成式,直接用 dict()
进行转换也是可以的。
但是当元组稍微复杂时,比如以下例子,元组中每个元组有三个值时,中间的为无效信息时,dict()
就会有歧义,而我们的字典生成器更灵活
tup = [('zhang','s', 0),('liu','s',1),('lan','s',2)]
print(dict(tup))
# 报错 ValueError: dictionary update sequence element #0 has length 3; 2 is required
dic = {k:v for k,_,v in tup} # _ 跳过第二个元素
# {'zhang': 0, 'liu': 1, 'lan': 2}
最常用的场景就是在nlp场景中的word2idx和idx2word,需要双向都能找到对应的值,利用集合列表的索引和单词实现双向转换
vocab = ['love', 'milk', 'coffee', 'like', 'hate', 'cat', 'i']
word2idx = {w:i for i,w in enumerate(vocab)}
# {'love': 0, 'milk': 1, 'coffee': 2, 'like': 3, 'hate': 4, 'cat': 5, 'i': 6}
idx2word = {i:w for i,w in enumerate(vocab)}
# {0: 'love', 1: 'milk', 2: 'coffee', 3: 'like', 4: 'hate', 5: 'cat', 6: 'i'}
还有一种常用的将字典中的键值对反转的场景,即key变value,value变key
Tips:要在遍历时同时用到key和value需要用到
dic.items()
# 已知一个word2idx的词典,转化idx2word
word2idx = {'zhang': 1, 'liu': 2, 'lan': 3}
idx2word = {index:word for word,index in word2idx.items()}
# {1: 'zhang', 2: 'liu', 3: 'lan'}
集合生成器相对于来说就更简单了,其语法为
set_ = {x for x in interable if condition}
比如要将句子转化为一个个字母词典且不需要空格时
s = 'hello world'
comp = {x for x in s if x != ' '}
# {'r', 'd', 'w', 'o', 'h', 'l', 'e'}
# 注意集合是无序的
type(comp)
#
如果直接想要将s的各个元素转化为不重复的分隔字母且不在乎空格时,可以不用集合生成器,因为有更简单的用法,直接用set()
即可
s = 'hello world'
comp = {x for x in s}
# {' ', 'r', 'o', 'd', 'e', 'h', 'l', 'w'}
# 直接用set就可以了!
comp = set(s)
# {' ', 'r', 'o', 'd', 'e', 'h', 'l', 'w'}结果一样