推导式是从一个或多个迭代器快速简洁的创建数据结构的一种办法,它可以将循环和条件判断结合,从而可以避免语法冗长的代码。
推导式:一行代码生成一个列表(字典、集合)
注意:元组没有推导式
基本语法:[结果 for循环 条件判断(可选)]
列表习题
例1:创建一个1到10的列表
解答:
(1)循环1
2
3
4lis = []
for i in range(1, 11):
lis.append(i)
print(lis)
(2)列表推导式1
2lis = [i for i in range(1, 11)]
print(lis)
例2:20以内的基数创建一个列表
解答:取余判断1lis = [ i for i in range(21) if i%2==1]
range步长1lis = [i for i in range(1,20,2)]
例3:100以内被3整除的数的平方组成一个新的列表使用range步长实现1lis = [i**2 for i in range(3, 100, 3)]
使用判断表达式实现1lis = [ i**2 for i in range(1, 100) if i%3==0]
例4:列表中包含两个e的名字组成一个新的列表返回使用for循环实现1
2
3
4
5
6names = [['tom', 'billy', 'jeffer', 'andrew', 'wesley', 'steven'], ['alice', 'jill', 'ada', 'eveal', 'eva', 'cherry']]
lis = []
for line in names:
for name in line:
if name.count('e') == 2:
lis.append(name)
使用列表推导式实现1
2names = [['tom', 'billy', 'jeffer', 'andrew', 'wesley', 'steven'], ['alice', 'jill', 'ada', 'eveal', 'eva', 'cherry']]
lis = [name for line in names for name in line if name.count('e') == 2]
字典推导式习题1语法:{key:value for循环 条件判断(可选)}
例1:使用字典推导式将[‘a’, ‘b’, ‘c’, ‘d’] 转换为 {0:’a’, 1:’b’, 2:’c’, 3:’d’}推导式使用range1
2lis = ['a', 'b', 'c', 'd']
dic = {i:lis[i] for i in range(len(lis))}
推导式使用enumerate1
2lis = ['a', 'b', 'c', 'd']
dic = {i:j for i, j in enumerate(lis)}
例2:将{‘jj’:’林俊杰’, ‘jay’:’周杰伦’, ‘jolin’:’蔡依林’}键与值对调形成新的字典1dic = {'jj':'林俊杰', 'jay':'周杰伦', 'jolin':'蔡依林'} res = {v:k for k,v in dic.items()} print(res)
集合推导式习题1集合:不可重复、可哈希
例:将以下列表去重[1, 3, 5, 3, 66, 4, 3, 5, 7]使用集合转换去重1
2lis = [1, 3, 5, 3, 66, 4, 3, 5, 7]
s = set(lis)
使用推导式去重1
2lis = [1, 3, 5, 3, 66, 4, 3, 5, 7]
s = {i for i in lis}
生成器表达式和列表推导式的区别:列表推导式比较耗内存. 一次性加载. 生成器表达式几乎不占用内存. 使用的时候才分 配和使用内存
得到的值不一样. 列列表推导式得到的是一个列表. 生成器表达式获取的是一个生成器.
生成器表达式: (结果 for 变量 in 可迭代对象 if 条件筛选)
生成器表达式可以直接获取到生成器对象. 生成器对象可以直接进行for循环. 生成器具有惰性机制.
生成器的惰性机制: 生成器只有在访问的时候才取值. 说白了. 你找他要他才给你值. 不找他要. 他是不会执行的.
下面放两个带坑面试题
1、以下代码运行结果是什么?(先不要看解释哟)1
2
3
4
5
6
7
8
9def func():
yield 222
g = func() # 生成器g
g1 = (i for i in g) # 生成器g1. 但是g1的数据来源于g
g2 = (i for i in g1) # 生成器g2. 来源g1
print(list(g)) # 获取g中的数据. 这时func()才会被执行. 打印111.获取到222. g完毕.
print(list(g1)) # 获取g1中的数据. g1的数据来源是g. 但是g已经取完了. g1 也就没有数据
了
print(list(g2)) # 和g1同理
答案:1
2
3[222]
[]
[]
2、以下代码运行结果是什么?1
2
3
4
5
6
7
8
9def add(a, b):
return a + b
def test():
for item in range(4):
yield item
g = test()
for n in [5, 10]:
g = (add(n, i) for i in g)
print(list(g))
答案:[20, 21, 22, 23]1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33以上代码分析:
首行add函数只是一个用来求和的迷惑函数
向下看
test()函数是一个生成器函数,可以看到它的值循坏下来为:0, 1, 2, 3
g = test()这行代码才开始获取生成器,然后继续向下看
for n in [5, 10]:
g = (add(n, i) for i in g)
这段代码我们来进行拆分一下变为:
n=5
g = (add(n, i) for i in g)
n=10
g = (add(n, i) for i in g)
print(list(g))
以上代码可以看出,n=5以后,我们并没有取生成器的值,所以5不会带进生成器表达式,只是执行了下一行代码g = (add(n, i) for i in g),
所以此时我们可以将代码再进行拼接下将n=10后的生成器表达式后面的g给替换为(add(n, i) for i in g)
n=10
g = (add(n, i) for i in (add(n, i) for i in g))
print(list(g))
此时我们才取值
所以可以把n等于10带进去
代码变为一下,为了区分循环变量i,我们将替换g表达式中的i改为index
g = (add(10, i) for i in (add(10, index) for index in g))
接下来我们一步一步开始走
g = (add(10, i) for i in (add(10, index) for index in [0, 1, 2, 3]))
继续
g = (add(10, i) for i in [10, 11, 12, 13])
继续g的值已经是20,21, 22, 23
print(list(g))
最后转为列表,结果当然就是[20, 21, 22, 23]