目录
推导式是什么
推导式(又称解析器),是 Python 独有的一种特性。 使用推导式可以快速生成列表、生成器、字典以及集合类型的数据。简单说可以理解为for循环的简写。
格式
普通的推导式
结果 for 变量 in 可迭代对象
带筛选的推导式
结果 for 变量 in 可迭代对象 if 表达式
上面的两个格式只是一个例子,不同的表达式使用的括号不同,上面两个只是括号里面的内容,并不是完整的推导式。四种推导式都是可以增加if语句的
注意:内部的for循环和if语句不需要加冒号!否则会报错
推导式的分类
- 列表推导式
- 元组推导式
- 字典推导式
- 集合推导式。
列表推导式
列表推导式比较占内存,一次性加载出来,这是4种推导式除了生成器推导式之外共有的缺点。
格式
[结果 for 变量 in 可迭代对象]
例子
li1 = [i for i in range(10)] # 列表推导式
print(li1)
# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
li2 = [i for i in range(10) if i % 2 == 0] # 带筛选的列表推导式
print(li2)
# [0, 2, 4, 6, 8]
li3 = ['第%s个' % i for i in range(1, 11)] # 结果直接格式化字符串的列表推导式
print(li3)
# ['第1个', '第2个', '第3个', '第4个', '第5个', '第6个', '第7个', '第8个', '第9个', '第10个']
生成器推导式
格式:
(结果 for 变量 in 可迭代对象)
生成器推导式的括号是圆括号,而不是方括号,使用生成器推导式后还是需要使用for循环的方式获取生成器内部的数据,因为其本质仍然是生成器。其优点也很明显,与生成器一样,几乎不占内存,使用前只会分配一个内存地址,使用的时候才会为内部数据进行分配和使用内存
例子
Builder1=(i for i in range(5))
print(Builder1) #此时获取的只是生成器的地址
# <generator object <genexpr> at 0x000001948B2AE110>
for i in Builder1:
print(i) #获取生成器里面的内容
'''
0
1
2
3
4
'''
Builder2=(i for i in range(5) if i%2==0)
print(Builder2)
for i in Builder2:
print(i)
'''
0
2
4
'''
字典推导式
字典推导式因为需要键和值,使用与其他的推导式不同。使用花括号
格式:
{键:值 for i in 可迭代对象}
list1=['你','我','他'] #键名
list2=['小明','小红','小亮'] #值
dict1={list1[i]:list2[i] for i in range(len(list1))}
print(dict1)
# {'你': '小明', '我': '小红', '他': '小亮'}
集合推导式
和字典推导式一样,是使用花括号括起来,但是不需要键名和值,而且集合推导式只带去重功能,并会将正负数分开。
格式
{结果 for i in 可迭代对象}
例子
lst = [1, 2, 3, -1, -2, -3, -7, 9] # 可迭代对象
set1 = {abs(i) for i in lst}
print(set1)
# {1, 2, 3, 7, 9}
使用推导式的好处
可以使代码更简洁。
#使用推导式之前
li1=[]
for i in range(1,11):
li1.append(i)
print(li1)
# [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
#使用推导式之后
li2=[i for i in range(1,11)]
print(li2)
# [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
可以看到生成一个1到10的列表,使用推导式之前需要3行,而使用推导式则只需要1行。但是并不能盲目的使用推导式,如果推导式过于长的话,还是需要考虑使用for循环比较好。使用推导式虽然简洁了,但是可读性变差了,发生了错误也不好寻找问题出在哪里。
例子:
# 提取下面字符串中含有两个及以上e的字符串
names = [["Tom", "Billy", "Jefferson", "Andrew", "Wesley", "Steven", "Joe"],
["Alice", "Jill", "Ana", "Wendy", "Jennifer", "Sherry", "Eva"]]
# 使用推导式之前
names_new1 = [] # 存放提前后的列表
for i in names: # 外层循环控制外部列表
for j in i: # 内部循环控制内部列表
if j.count('e') >= 2: # 如果字符串中有两个及以上的e
names_new1.append(j) # 则追加到上面的空列表中
print(names_new1)
# ['Jefferson', 'Wesley', 'Steven', 'Jennifer']
# 使用推导式后
names_new2 = [j for i in names for j in i if j.count('e') >= 2] # 思路与上面的一样
print(names_new2)
# ['Jefferson', 'Wesley', 'Steven', 'Jennifer']
这个例子中,虽然使用推导式之后只需要1行就可以提取出来,但是可读性却大大降低了,而且出现了错误也不方便排查。