推导式
在 py 中满足推导式的只有 列表、字典、集合,
- 列表推导式
- 字典推导式
- 集合推导式
所谓的推导式其实就是更有 py 风格的一种代码写法,比如原本有一个需求需要通过 3-5 行代码实现,但是用了推导式我们只需要一行代码即可,也就是说同样的需求推导式的代码量更少,所以推导式的重用就是用于化简代码使用
1 列表推导式
作用: 用一个表达式创建一个有规律的列表或控制一个有规律列表。
列表推导式又叫列表生成式。
1.1 快速体验
需求:创建一个 0-9 的列表
在下面我将通过 3 种方法实现,第一种是传统的 while 循环实现,第二种是通过 for 实现,第三种基于推导式实现,由此来观察三者之间的代码量
while
循环实现
# 创建列表
list1 = []
# 定义初始化变量
i = 0
# 基于 i < 10 的 while 循环,在通过 list1.append 函数每次将 i 追加=至 list1 中
while i < 10:
list1.append(i)
# 退出循环判断条件,i 自增为 1
i+=1
print(list1)
[08:55:36 root@dev py-demo]#/bin/python3 /root/py-demo/day-1/test.py
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
for
循环实现
# 创建列表
list1 = []
# 基于 range(10) 为循环次数
for i in range(10):
# 每次 append 追加 1
list1.append(i)
print(list1)
[09:11:26 root@dev py-demo]#/bin/python3 /root/py-demo/day-1/test.py
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
类型推导实现:
# list1 = 这就是一个变量赋值
# [i for i in range(10)] 这就是一个列表推导式
# 为什么使用 [] ,因为我们是一个列表推导式,而返回的数据是一个列表所以我们需要将其放到一个[]中
list1 = [i for i in range(10)]
print(list1)
[09:12:46 root@dev py-demo]#/bin/python3 /root/py-demo/day-1/test.py
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
1.2 带 if 的列表推导式
需求: 创建0-10的偶数列表
方法一:range
步长实现
# 我们都知道在写 range 的时第三个参数为步长,所以可以基于步长为 2 进行获取偶数
list1 = [i for i in range(0,10,2)]
print(list1)
[10:10:06 root@dev py-demo]#/bin/python3 /root/py-demo/day-1/test.py
[0, 2, 4, 6, 8]
但是上面的这种写法很明显不符合 if 的需求
方法二:for 循环加 if 创建有规律列表,基于 append()
实现追加
list2 = []
for i in range(10):
# i % 2 == 0 为真就执行 list2.append(i) 实现 i 追加至 list2
if i % 2 == 0:
list2.append(i)
print(list2)
[10:15:42 root@dev py-demo]#/bin/python3 /root/py-demo/day-1/test.py
[0, 2, 4, 6, 8]
方法三:通过 推导式 和 if 实现
# 先实现 i 的推导式,然后基于 if 判断 i % 2 == 0 为真返回给 list12
list12 = [i for i in range(10) if i % 2 == 0]
print(list12)
[10:15:41 root@dev py-demo]#/bin/python3 /root/py-demo/day-1/test.py
[0, 2, 4, 6, 8]
注意:
只要是带 for 循环和 if 的推导式,都只需要将 :
和回车换行去掉即可实现
1.3 多个 for 循环实现列表推导式
需求:创建如下列表
[(1, 0),(1, 1),(1, 2), (2, 0),(2,1), (2, 2)]
# 在上面的数据中,我们可以观察到前三个数据中其实第一个数据都是 1 ,而后三个则是 2。
# 说明第一个数据块的起始循环为 1,而第二个起始循环为 2,所以这就是外层循环 1-2 循环两次
# 而在每一个数据块中可以看到第二次循环为 0 1 2 ,这就是内层循环 0-2
普通代码实现:
list1 = []
for i in range (1,3):
for j in range(3):
# 列表里面追加元组:循环前准备一个空列表,然后在这里追加元组数据到列表
list1.append((i,j))
print(list1)
推导代码实现:
# 第一个 for 通过 i 接收返回值,第二个 for 通过 j 接收返回值,并传递个外部 (i,j)
list1 = [(i,j) for i in range(1,3) for j in range(3)]
print(list1)
[10:19:27 root@dev py-demo]#/bin/python3 /root/py-demo/day-1/test.py
[(1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]
2 字典推导
思考: 如果有如下两个列表
list1 = ['name','age','gender']
list2 = ['Tom', 20, 'man']
如何快速合并为一个字典?
答:字典推导式
字典推导式作用: 快速合并列表为字典或提取字典中目标数据
2.1 快速体验
1 创建一个字典: 字典key是1-5数字,value是这个数字的2次方
# 因为需要字典,所以我们将代码放置大括号中
dict1 = {i : i**2 for i in range(1,5)}
print(dict1)
[14:46:10 root@dev py-demo]#/bin/python3 /root/py-demo/day-1/test.py
{1: 1, 2: 4, 3: 9, 4: 16}
2.2 将两个列表合并为一个字典
# 由于 list1 和 list2 中的下标长度都为 3 所以可以直接基于 len(list1) 实现单独对列表的取值
list1 = ['name','age','gender']
list2 = ['tom',28,'男']
# 注意:使用这种方法的前提需要知道两个列表下标长度是否一样,数据是否能够实现匹配
dict1 = {lits1[i] : list2[i] for i in range(len(lits1))}
print(dict1)
[14:54:14 root@dev py-demo]#/bin/python3 /root/py-demo/day-1/test.py
{'name': 'tom', 'age': 28, 'gender': '男'}
测试:当列表个数不相同时会发生什么情况:
# 将 list1 添加至下标为 4 的数据内容
list1 = ['name','age','gender',22]
list2 = ['tom',28,'男']
dict1 = {lits1[i] : list2[i] for i in range(len(lits1))}
print(dict1)
[15:01:35 root@dev py-demo]#/bin/python3 /root/py-demo/day-1/test.py
Traceback (most recent call last):
File "/root/py-demo/day-1/test.py", line 5, in <module>
dict1 = {list1[i] : list2[i] for i in range(len(lits1))}
File "/root/py-demo/day-1/test.py", line 5, in <dictcomp>
dict1 = {list1[i] : list2[i] for i in range(len(lits1))}
IndexError: list index out of range
# 可以看到报错超出索引范围,因为在 list2 中没有下标为 3 的数据
但是取 list2
的值就没有问题,因为在 list1
中包含 0-2 所有下标的值
# 将 list1 添加至下标为 4 的数据内容
list1 = ['name','age','gender',22]
list2 = ['tom',28,'男']
dict1 = {lits1[i] : list2[i] for i in range(len(list2))}
print(dict1)
[15:08:35 root@dev py-demo]#/bin/python3 /root/py-demo/day-1/test.py
{'name': 'tom', 'age': 28, 'gender': '男'}
总结:
- 如果两个列表元素个数相同,
len
统计任何一个列表的长度都可以 - 如果两个列表元素个数不同,
len
统计元素多的列表就会报错超出索引范围,但是len
统计元素少的列表个数就不会报错
2.3 提取字典中的目标数据
什么场景下需要提取目字典中的目标数据
如下面代码:
举个场景,比如我们公司是卖电脑的,比如下面 counts 是一个月内不同品牌的电脑销售台数,这个时候领导需要查看那些电脑卖出的量大于两百并需要将数据提取出来,用于下个月将这些出售量大于两百的电脑多备点货。
那么这个时候就需要涉及到提取字典中的目标数据
# 在下面字典中是各个品牌电脑的个数
counts = {'MAC':268 , 'HP':110 , 'DELL':201 , 'LENOVO':332 , 'ACER':99 }
# 需求:将上述数据中大于 200 的数据进行提取
'''
通过 counts.items() 函数实现
items() 函数将返回迭代器包含 k,v 的值,并返回给 k:v 两个变量
再基于 v 是否做 if 判断是否大于 200,如果大于就将该 v 和对应的 k 进行返回给 k:v
'''
counts2 = {k : v for k , v in counts.items() if v >= 200}
print(counts2)
[15:21:47 root@dev py-demo]#/bin/python3 /root/py-demo/day-1/test.py
{'MAC': 268, 'DELL': 201, 'LENOVO': 332}
3 集合
集合推导式在工作中的使用概率并没有列表和字典推导式这么高,所以对于集合推导式我们快速看一下
需求: 创建一个集合,数据为下方列表的2次方
list1 = [1,2,3]
# 对 list1 做 for-i 循环,再赋值给 i 变量,最后 i**2 实现 2 次方
set1 = {i ** 2 for i in list1}
print(set1)
[15:23:56 root@dev py-demo]#/bin/python3 /root/py-demo/day-1/test.py
[1, 4, 9]
注意:set 有数据去重功能如下代码
list1 = [2,2,3]
# 如下代码可以看到 list1 列表中包含了两个元素为 2 的数据
set1 = {i ** 2 for i in list1}
print(set1)
# 可以看到只输出了一个 4 ,所以由此可见 set 具有去重功能
[15:34:03 root@dev py-demo]#/bin/python3 /root/py-demo/day-1/test.py
{9, 4}
4 总结
- 推导式的作用:简化代码
- 推导式的写法:
# 列表推导式
[xx for xx in range()]
# 字典推导式
{xx1:xx2 for ... in ...}
# 集合推导式
{xx for xx in ...}