Day13 推导式、推导式试题、集合推导式、生成器函数、生成器表达式

 1.推导式

通过一行循环判断,遍历出一系列数据的方式就是推导式
特点:方便,简介,可以实现一些简单的功能
推导式当中只能跟循环和判断(单项分支)
种类中分为三种: 列表推导式,集合推导式,字典推导式
[val  for val in  iterable]
{val for val in iterable}
{a:b for a,b in iterable}

1.1基本语法
# [1,2,3,4]  => [2,4,6,8]
lst = [1,2,3,4]
lst2 = []
for i in lst:
    res = i * 2
    lst2.append(res)
print(lst2)


# 改写
res = [i * 2 for i in range(1, 5)]
print(res)

# [1,2,3,4]  => [2,8,24,64]
'''
1-> 2   乘以2的1次幂
2-> 8   乘以2的2次幂
3 -> 24 乘以2的3次幂
4 -> 64 乘以2的4次幂
'''
# 把想要的值 写在for的左侧
res = [i << i for i in range(1,5)] # 1 << 1  2 << 2 3 << 3 4<<4
print(res)

1.2带有条件判断的推导式

lst = [1, 2, 3, 4, 5, 6, 67, 7, 8, 98, 9]
lst2 = []
for i in lst:
    if i % 2 == 0:
        lst2.append(i)
print(lst2)

# 推导式写法
res = [i for i in lst if i %2 == 0]
print(res) # 求的都是偶数

 

1.3多循环推导式
lst1 = ["邓远文","舒畅","易思","仿真枪"]
lst2 = ["张国成","王博","邱玉龙","苏传红"]
lst = []
for i in lst1:
    for j in lst2:
        res = i + '♥♥♥' +j
        lst.append(res)
print(lst)
# "谁 ♥♥♥ 谁"
#改写
res = [i+'♥♥♥'+j for i in lst1 for j in lst2 ]
print(res)
运行结果:
['邓远文♥♥♥张国成', '邓远文♥♥♥王博', '邓远文♥♥♥邱玉龙', '邓远文♥♥♥苏传红',
'舒畅♥♥♥张国成', '舒畅♥♥♥王博', '舒畅♥♥♥邱玉龙', '舒畅♥♥♥苏传红',
'易思♥♥♥张国成', '易思♥♥♥王博', '易思♥♥♥邱玉龙', '易思♥♥♥苏传红',
'仿真枪♥♥♥张国成', '仿真枪♥♥♥王博', '仿真枪♥♥♥邱玉龙', '仿真枪♥♥♥苏传红']
 
   

 

1.4带有循环判断的推导式
# 个人理解就是只要和for循环相关的,不论是一个还是多个for循环,一旦从循环里面出来的时候,条件只需要判断一下就可以得到结果的都可以使用
推导式来做。也就是从for循环出来的时候,只需要一个判断条件得到结果放在列表中。(1.1-1.4都是这样的)
要求:1.3的例子不变,但是是对应索引的相爱想杀。
lst1 = ["邓远文","舒畅","易思","仿真枪"]
lst2 = ["张国成","王博","邱玉龙","苏传红"]
lst_new = []
for i in lst1:
    for j in lst2:
        if lst1.index(i) == lst2.index(j):
            strvar = i+'♥♥♥'+j
            lst_new.append(strvar)

print(lst_new)
# 推导式写法
res = [i+'♥♥♥'+j for i in lst1 for j in lst2  if lst1.index(i) == lst2.index(j)]
print(res)
# ['邓远文♥♥♥张国成', '舒畅♥♥♥王博', '易思♥♥♥邱玉龙', '仿真枪♥♥♥苏传红']
 
   

 

2.推导式试题
总结:写列表推导式的时候可以先写简单的函数顺便用来转换,注意多选的时候,列表表达式前面部分为列表表达式最后面的判断条件后要执行的代码。
#(1).{'x': 'A', 'y': 'B', 'z': 'C' } 把字典写成x=A,y=B,z=C的列表推导式
dic = {
     'x': 'A', 'y': 'B', 'z': 'C' }
# for  a,b in dic.items():
    # print(a,b)
res = [a+"="+b for a,b in dic.items() ]
print(res)

# (2).把列表中所有字符变成小写  ["ADDD","dddDD","DDaa","sss"]
lst = ["ADDD","dddDD","DDaa","sss"]
res = [i.lower() for i in  lst ]
print(res)

# (3).x是0-5之间的偶数,y是0-5之间的奇数 把x,y组成一起变成元组,放到列表当中
# (0 2 4 )
# (1 3 5)
# (0 1) (0 3) (0 5)
# (2 1) (2 3) (2 5)
# (4 1) (4 3) (4 5)
lst_new = []

for i in range(0,6):
    if i % 2 == 0:
        for j in range(0,6):
            if j % 2 == 1:
                lst_new.append( (i,j) )

print(lst_new)

# 写法一
res = [(i,j) for i in range(0,6) if i % 2 == 0 for j in range(0,6) if j % 2 == 1  ]
print(res)
lst_new2 = []
for i in range(0,6):
    for j in range(0,6):
        if i % 2==0 and j %2 ==1:
            lst_new2.append( (i,j) )
print(lst_new2)


# 写法二
res = [(i,j) for  i in range(0,6) for j  in range(0,6) if i % 2 == 0 and j % 2 == 1 ]
print(res)



# (4).使用列表推导式 制作所有99乘法表中的运算
for i in range(1,10):
    for j in range(1,i+1):
        # print("%d*%d=%2d " % (i,j,i*j))
        print("{:d} * {:d} = {:2d} ".format(i,j,i*j) ,end="")
        
    print()

# 写法一
res = ["{:d} * {:d} = {:2d} ".format(i,j,i*j) for i in range(1,10) for j in range(1,i+1)]
print(res)

for i in range(9,0,-1):
    for j in range(1,i+1):
        # print("%d*%d=%2d " % (i,j,i*j))
        print("{:d} * {:d} = {:2d} ".format(i,j,i*j) ,end="")
        
    print()    
# 写法二
res = ["{:d} * {:d} = {:2d} ".format(i,j,i*j) for i in range(9,0,-1) for j in range(1,i+1)]
print(res)

'''
(5)#求M,N中矩阵和元素的乘积
# M = [ [1,2,3], 
#       [4,5,6], 
#       [7,8,9]  ] 

# N = [ [2,2,2], 
#       [3,3,3], 
#       [4,4,4]  ] 
=>实现效果1   [2, 4, 6, 12, 15, 18, 28, 32, 36]
=>实现效果2   [[2, 4, 6], [12, 15, 18], [28, 32, 36]]
'''
M = [[1,2,3],[4,5,6],[7,8,9]]
N = [[2,2,2],[3,3,3],[4,4,4]]

# M[0][0] * N[0][0] = 2
# M[0][1] * N[0][1] = 4
# M[0][2] * N[0][2] = 6


# M[1][0] * N[1][0] = 12
# M[1][1] * N[1][1] = 15
# M[1][2] * N[1][2] = 18


# M[2][0] * N[2][0] = 28
# M[2][1] * N[2][1] = 32
# M[2][2] * N[2][2] = 36

# 效果1  # i=> 0 1 2  j=> 0 1 2 i动的慢 j动的块
res = [M[i][j] * N[i][j] for i in range(3) for j in range(3) ]
print(res) #[2, 4, 6, 12, 15, 18, 28, 32, 36]

#=>实现效果2   [    [2, 4, 6], [12, 15, 18], [28, 32, 36]    ]

# [] [] [] 
'''
第一步遍历三个空列表
[ []  for i in range(3)  ]
第二部在空列表里面在写一个推导式遍历对应的元素
[M[i][j] * N[i][j]  for j in range(3)]
'''
res = [   [M[i][j] * N[i][j]  for j in range(3)]  for i in range(3)   ]
print(res) #[[2,4,6], [], []]

运行结果:

['x=A', 'y=B', 'z=C']
['addd', 'ddddd', 'ddaa', 'sss']
[(0, 1), (0, 3), (0, 5), (2, 1), (2, 3), (2, 5), (4, 1), (4, 3), (4, 5)]
[(0, 1), (0, 3), (0, 5), (2, 1), (2, 3), (2, 5), (4, 1), (4, 3), (4, 5)]
[(0, 1), (0, 3), (0, 5), (2, 1), (2, 3), (2, 5), (4, 1), (4, 3), (4, 5)]
[(0, 1), (0, 3), (0, 5), (2, 1), (2, 3), (2, 5), (4, 1), (4, 3), (4, 5)]
1 * 1 = 1
2 * 1 = 2 2 * 2 = 4
3 * 1 = 3 3 * 2 = 6 3 * 3 = 9
4 * 1 = 4 4 * 2 = 8 4 * 3 = 12 4 * 4 = 16
5 * 1 = 5 5 * 2 = 10 5 * 3 = 15 5 * 4 = 20 5 * 5 = 25
6 * 1 = 6 6 * 2 = 12 6 * 3 = 18 6 * 4 = 24 6 * 5 = 30 6 * 6 = 36
7 * 1 = 7 7 * 2 = 14 7 * 3 = 21 7 * 4 = 28 7 * 5 = 35 7 * 6 = 42 7 * 7 = 49
8 * 1 = 8 8 * 2 = 16 8 * 3 = 24 8 * 4 = 32 8 * 5 = 40 8 * 6 = 48 8 * 7 = 56 8 * 8 = 64
9 * 1 = 9 9 * 2 = 18 9 * 3 = 27 9 * 4 = 36 9 * 5 = 45 9 * 6 = 54 9 * 7 = 63 9 * 8 = 72 9 * 9 = 81

9 * 1 = 9 9 * 2 = 18 9 * 3 = 27 9 * 4 = 36 9 * 5 = 45 9 * 6 = 54 9 * 7 = 63 9 * 8 = 72 9 * 9 = 81
8 * 1 = 8 8 * 2 = 16 8 * 3 = 24 8 * 4 = 32 8 * 5 = 40 8 * 6 = 48 8 * 7 = 56 8 * 8 = 64
7 * 1 = 7 7 * 2 = 14 7 * 3 = 21 7 * 4 = 28 7 * 5 = 35 7 * 6 = 42 7 * 7 = 49
6 * 1 = 6 6 * 2 = 12 6 * 3 = 18 6 * 4 = 24 6 * 5 = 30 6 * 6 = 36
5 * 1 = 5 5 * 2 = 10 5 * 3 = 15 5 * 4 = 20 5 * 5 = 25
4 * 1 = 4 4 * 2 = 8 4 * 3 = 12 4 * 4 = 16
3 * 1 = 3 3 * 2 = 6 3 * 3 = 9
2 * 1 = 2 2 * 2 = 4
1 * 1 = 1

[2, 4, 6, 12, 15, 18, 28, 32, 36]
[[2, 4, 6], [12, 15, 18], [28, 32, 36]]

 
   

 

3.集合推导式
案例:
满足年龄在18到21,存款大于等于5000 小于等于5500的人,
开卡格式为:尊贵VIP卡老x(姓氏),否则开卡格式为:抠脚大汉卡老x(姓氏)
把开卡的种类统计出来
 
   
listvar = [
    {
      "name":"王家辉","age":18,"money":10000},
    {
      "name":"王水机","age":19,"money":5100},
    {
      "name":"王鹏","age":20,"money":4800},
    {
      "name":"李站","age":21,"money":2000},
    {
      "name":"李小龙","age":180,"money":20}
]
setvar = set()
for i in listvar:
    if 18 <= i['age'] <= 21 and 5000 <= i['money'] <= 5500:
        strvar = "尊贵VIP卡老" + i["name"][0]
        setvar.add(strvar)
    else:
        strvar = "抠脚大汉卡老" + i['name'][0]
        setvar.add(strvar)
print(setvar)

# 真值 if 条件表达式 else 假值
# 第一部分 for i in listvar
# 第二部分 三目运算符:"尊贵VIP卡老" + i["name"][0] if 18 <= i['age']<=21 and 5000<=i['money']<=5500 else "抠脚大汉卡老" + i['name'][0]

res = {
     "尊贵VIP卡老" + i["name"][0] if 18 <= i['age']<=21 and 5000<=i['money']<=5500 else "抠脚大汉卡老" + i['name'][0] for i in listvar}
print(res)
运行结果:

{'抠脚大汉卡老王', '抠脚大汉卡老李', '尊贵VIP卡老王'}
{'抠脚大汉卡老王', '抠脚大汉卡老李', '尊贵VIP卡老王'}

 
   

 

4.字典推导式
4.1enumerate
enumerate(iterable,[start=0])
功能:枚举 ; 将索引号和iterable中的值,一个一个拿出来配对组成元组放入迭代器中
参数:
    iterable: 可迭代性数据 (常用:迭代器,容器类型数据,可迭代对象range) 
    start:  可以选择开始的索引号(默认从0开始索引)
返回值:迭代器
 
   

 

 
   
listvar = ["马军强", "何键翰", "郑国成", "境泽年"]
it = enumerate(listvar)
from collections import Iterator,Iterable
print(isinstance(it, Iterator))
# (1) 使用next进行调用
res = next(it)#第一个
print(res
res = next(it)
print(res)#第二个
# (2) 使用for 来调用
for i in it:#第三个
    print(i)# 第四个
# (3) 用list瞬间得到所有数据
it = enumerate(listvar)
lst = list(it)
print(lst) #[(0, '马军强'), (1, '何键翰'), (2, '郑国成'), (3, '境泽年')]

# 利用enumerate 变成字典推导式
res = {a: b for a, b in enumerate(listvar)}
print(res)


# 使用dict强转迭代器
res = dict(enumerate(listvar))
print(res)

# start 可以选择从第几个数值开始数数
res = dict(enumerate(listvar,start=14))
print(res)
运行结果为:

True
(0, '马军强')
(1, '何键翰')
(2, '郑国成')
(3, '境泽年')
[(0, '马军强'), (1, '何键翰'), (2, '郑国成'), (3, '境泽年')]
{0: '马军强', 1: '何键翰', 2: '郑国成', 3: '境泽年'}
{0: '马军强', 1: '何键翰', 2: '郑国成', 3: '境泽年'}
{14: '马军强', 15: '何键翰', 16: '郑国成', 17: '境泽年'}

 
   

 

4.2 zip()
zip(iterable, ... ...)
    功能: 将多个iterable中的值,一个一个拿出来配对组成元组放入迭代器中
    iterable: 可迭代性数据 (常用:迭代器,容器类型数据,可迭代对象range) 
返回: 迭代器
 
   
# (1)zip 自动配对,如果长度超出了,自动舍弃
lst1 = ["许经雄","刘五星","正路","易思"]
lst2 = ["英俊潇洒","疯牛踢躺","柔情似水","抠脚大汉",1,2,3,4]
it = zip(lst1,lst2)
print(isinstance(it,Iterator))

# 使用for 搭配next 进行调用
for i in range(3):
    res = next(it)#1 #2 #3
    print(res)

for i in it:#4
    print(i)

# 利用zip实现字典推导式
res = {a:b for a,b  in zip(lst1,lst2)}
print(res)

# 使用dict强转迭代器
res = dict(zip(lst1,lst2))
print(res)

# (2)用两个列表 实现如下字典:
# 'hxd':'黄熊大'
# 'jzl':'将周郎'
# 'cgt':'陈桂涛'
dic1 = {
     'hxd':"胸大","jzl":"牛逼","cgt":"帅气"}
dic2 = {0:"黄熊大",1:"将周郎",2:"陈桂涛"}


lst_keys = dic1.keys()
# print(lst_keys)
# print(isinstance(lst_keys,Iterator))
# print(isinstance(lst_keys,Iterable))
lst_values = dic2.values()
# print(lst_values)
# print(isinstance(lst_values,Iterator))
# print(isinstance(lst_values,Iterable))

it = zip(lst_keys,lst_values)
print(it)

# 使用字典推导式实现
res = {a:b for a,b in it}
print(res)
# 使用dict强转迭代器实现
it = zip(lst_keys,lst_values)
res = dict(it)
print(res)
运行结果为:

True
('许经雄', '英俊潇洒')
('刘五星', '疯牛踢躺')
('正路', '柔情似水')
('易思', '抠脚大汉')
{'许经雄': '英俊潇洒', '刘五星': '疯牛踢躺', '正路': '柔情似水', '易思': '抠脚大汉'}
{'许经雄': '英俊潇洒', '刘五星': '疯牛踢躺', '正路': '柔情似水', '易思': '抠脚大汉'}

{'hxd': '黄熊大', 'jzl': '将周郎', 'cgt': '陈桂涛'}
{'hxd': '黄熊大', 'jzl': '将周郎', 'cgt': '陈桂涛'}

 
   

 

5.生成器

#生成器本质是迭代器,允许自定义逻辑的迭代器

#迭代器和生成器区别:
    迭代器本身是系统内置的.重写不了.而生成器是用户自定义的,可以重写
    迭代逻辑

#生成器可以用两种方式创建:
    (1)生成器表达式  (里面是推导式,外面用圆括号)
    (2)生成器函数    (用def定义,里面含有yield)

 

 
   

#(1) 生成器表达式 generator

# [1,2,3,4] => [4,8,12,16]
# i << 2 i乘以2的2次幂
gen = (i << 2 for i in range(1,5))
print(gen)
# at 0x00000000021ED570>
from collections import Iterator,Iterable print(isinstance(gen,Iterator))
# True

 

#(2)使用next进行调用生成器

res = next(gen)
print(res)
res = next(gen)
print(res)
res = next(gen)
print(res)
res = next(gen)
print(res)
# res = next(gen) 小心越界
# print(res)
# 4 8 12 16

 

#(3)使用for循环调用生成器

gen = (i << 2 for i in range(1,5))
for i in gen:
    print(i)
# 4 8 12 16

#(4)用for 和next 搭配调用生成器

 

gen = (i << 2 for i in range(1,5))
for i in range(2):
    res = next(gen)
    print(res)
# 4 8

 

 

6.生成器函数

 

(用def定义,里面含有yield)
# yield 类似于 return
共同点在于:执行到这句话都会把值返回出去
不同点在于:yield每次返回时,会记住上次离开时执行的位置 , 下次在调用生成
器 , 会从上次执行的位置往下走
           而return直接终止函数,每次重头调用.
yield 6 和 yield(6) 2种写法都可以 yield 6 更像 return 6 的写法 推荐使用
# (1) 基本使用
'''如果函数当中包含了yield ,那么这个函数是生成器函数'''
def mygen():
    print("one")
    yield 1
    print("two")
    yield 2
    print("three")
    yield 3

# 初始化生成器函数  => 返回一个生成器对象 ,简称生成器
gen = mygen()
print(isinstance(gen,Iterator))
# 调用生成器
res = next(gen)
print(res)
res = next(gen)
print(res)
res = next(gen)
print(res)
# res = next(gen)
# print(res)
'''
代码解析:
首先初始化生成器函数 返回生成器对象 简称生成器
同过next进行调用

第一次调用时
print(one)
yield 1  记录当前代码执行的位置状态,添加阻塞,暂停在这一行,并返回1,等待下一次调用

第二次调用时候
print(two)
yield 2  记录当前代码执行的位置状态,添加阻塞,暂停在这一行,并返回2,等待下一次调用

第三次调用时候
print(three)
yield 3  记录当前代码执行的位置状态,添加阻塞,暂停在这一行,并返回3,等待下一次调用

第四次调用时
因为没有yield 返回值了 所以直接报错....
如果仍然想要执行后面没走完的代码,比如95 96 ,那么要通过try ... except 异常
处理来解决
try:
lst = [1,2]
print(lst[99])
except:
pass
 

 

 
### yield from : 将一个可迭代对象变成一个迭代器返回    
def mygen():
    # yield ["陈桂涛","五金玲","张俊林"]
    yield from ["陈桂涛","五金玲","张俊林"]

# 初始化一个生成器函数mygen  返回生成器
gen = mygen()
res = next(gen)
print(res)
res = next(gen)
print(res)
res = next(gen)
print(res)


# 用生成器写斐波那契数列
# 1,1,2,3,5,8,13,21.......
def mygen(n):
    a = 0 
    b = 1
    i = 0
    while i<n:
        # print(b)
        yield b
        a,b = b,a+b        
        i+=1
gen = mygen(100000)
for  i in range(20):
    res  = next(gen)
    print(res)

'''
a = 0
b = 1
a,b = b,a
'''
 
   

 

 
   

 

转载于:https://www.cnblogs.com/longerandergou/p/10923924.html

你可能感兴趣的:(Day13 推导式、推导式试题、集合推导式、生成器函数、生成器表达式)