这其实是python中提供的遍历、筛选一个序列(如list,set,dict)中元素的特殊语法,其本质为在for loop 中对一个序列中元素执行指定的操作,要实现一个comprehension语法,我们需要确定四个要素:目标序列,目标元素,遍历,筛选条件。
假设我们有一个list
strings = ['list','set','dict','tuple']
现在我们想得到另一个list,这个list中只含有strings中长度为4的字符串(‘list’和‘dict’),很显然,我们可以通过一个循环解决,例如
newstrings = []
for word in strings:
if len(word) == 4:
newstrings.append(word)
python中有一种特殊的语法能够替代上面的写法,这就是list comprehension
newstrings = [x for x in strings if len(x) == 4]
上面的写法体现出了我们在文章开头提到的四要素,最外层的’[ ]'表明我们的目标序列是一个list,从左往右数的第一个x表明新的list中的元素就是原来list中的元素,后面紧跟的for表明我们正在遍历一个序列,if表明我们正在筛选这个序列中的元素。通过修改这四个元素,我们能够得到其它的序列。
newset = {len(x) for x in strings}
上面的语句得到含有strings中元素长度的set,{3,4,5}。
如果我们想要使用dict comprehension得到一个dict对象,我们首先要有一个特殊的序列,该序列的每个元素本身就是一个含有两个元素的序列,因为这样我们才能通过原有序列的一个元素得到一个key-value对。还是利用上文的strings,我们构建一个由字符串和其长度组成的key-value对构成的dict对象。
lengthlist = [len(x) for x in strings]
newdict = {key:value for key,value in zip(strings,lengthlist)}
newdict = {‘list’: 4, ‘set’: 3, ‘dict’: 4, ‘tuple’: 5}
注:如果想要使用tuple comprehension,需要写成下面的形式,即加上类型转换符
newtuple = tuple(x for x in strings)
假设我们有下面的一个list对象,其每个元素都是一个list
all_names = [['David','Tom','Peter'],['Steven','Jenny'],['Tim','Lily']]
现在我想提取出其中含有两个或两个‘e’的名字,应该怎么做?
一种方法是用循环+list comprehension
target = []
for names in all_names:
target.append([name for name in names if name.count('e') >= 2)
我们还可以用一句搞定,这就是nested list comprehension
target = []
target.append([name for names in all_names for name in names if name.count('e') >= 2]
两个for放在一句中看起来让人有点懵,其实上述语句就相当于下面的语句
for names in all_names:
for name in names:
...
首先遍历all_names中的每个元素(即names,为一个list),再遍历names中的每个元素(即name),这样就实现了两层遍历。
1.list,set,dict comprehension 实质上是一个for loop,只是语法上更精炼。
2.list,set,dict comprehension有四要素,即目标序列,目标元素,遍历,筛选条件。
3.nested list comprehension实质上是多层for loop嵌套,在语法上特别要注意多层for 的前后顺序。