加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Python > 正文

day14:列表/集合/字典推导式&生成器表达式&生成器函数

发布时间:2020-12-20 09:55:55 所属栏目:Python 来源:网络整理
导读:推导式 推导式的定义:?通过 一行循环 判断,遍历一系列数据的方式 推导式的语法: val for val in Iterable 三种方式: [val for val in Iterable] {val for val in Iterable} {k:v for k,v in Iterable} 列表推导式 1.单循环推导式 将[1,2,3,4,5] - [3,6,9,12,

推导式

推导式的定义:?通过一行循环判断,遍历一系列数据的方式

推导式的语法:

val for val in Iterable

三种方式:

  [val for val in Iterable]

  {val for val in Iterable}

  {k:v for k,v in Iterable}

列表推导式

1.单循环推导式

将[1,2,3,4,5] -> [3,6,9,12,15]

# 1.单循环推导式 [1,15]
lst = [1,5]
lst_new = []
for i in lst:
    res = i * 3
    lst_new.append(res)
print(lst_new)

 改写成推导式
lst = [i*3  lst]
print(lst)

2.带有判断条件的单循环推导式

 2.带有判断条件的单循环推导式 (只能是单项分支,接在for后面)
lst = [1,5,7,8 lst:
    if i % 2 == 1:
        lst_new.append(i)
 改写成推导式
lst = [i in lst ]
print(lst)

3.双循环推导式

 3. 双循环推导式
lst1 = ["A",BCD"]
lst2 = [XYZQ "谁"?"谁"
lst_new = lst1:
    for j  lst2:
        strvar = i + ?" + j
        lst_new.append(strvar)
 改写成推导式
lst = [i + " + j in lst1  lst2]
print(lst)

4.带有判断条件的多循环推导式

 4.带有判断条件的多循环推导式
lst_new = lst2:
        if lst1.index(i) == lst2.index(j):
            strvar = i +  j
            lst_new.append(strvar)        
 改写成推导式
lst = [ i + in lst2  lst2.index(j) ]
print(lst)

推导式练习题

1.{'x': 'A','y': 'B','z': 'C' } 把字典写成x=A,y=B,z=C的列表推导式

 使用等号"="进行拼接
lst = [k + =" + v for k,v  dic.items()]
print(lst)

2.x是0-5之间的偶数,y是0-5之间的奇数 把x,y组成一起变成元组,放到列表当中

 方法一
lst = [(x,y) for x in range(6) for y if x % 2 == 0 and y % 2 == 1(lst)

 方法二
lst = [(x,1)">if y % 2 == 1print(lst)

3.使用列表推导式 制作所有99乘法表中的运算

 for前面是一个format字符串的格式化
lst = [{}*{}={:2d} ".format(i,j,i*j) in range(9,-1) in range(1,i+1) ]
print(lst)

4.求M,N中矩阵和元素的乘积

M = [? [1,3],?
??   [4,6],?
??   [7,8,9] ]?

N = [? [2,2],?
??   [3,4] ]?
=>实现效果1 [2,15,18,28,32,36]
=>实现效果2 [[2,[12,18],[28,36]]

 实现思路
M = [[1,[4,[7,9]]
N = [[2,[3,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

外层的循环动的慢,内层的循环动的快,外层的循环动一次,内层的循环动3次,利用这个规律取出对应下标,乘积即可.
"""

 效果一  [2,36]
lst = [M[i][j] * N[i][j] in range(3) in range(3)]
 效果二 [[2,36]]
# 1 . 先遍历出三个空列表
lst = [  [] in range(3)  ]   =>  [ [],[],[] ]
 2 . 把空列表中的数据在通过推导式算出所有内容
lst = [ [M[i][j] * N[i][j] in range(3)]  print(lst)

集合推导式

关于集合推导式的一个示例:

1.集合有自动去重的效果

2.用三元表达式+推导式即可实现


案例:
    满足年龄在18到21,存款大于等于5000 小于等于5500的人,开卡格式为:尊贵VIP卡老x(姓氏),否则开卡格式为:普通用户卡老x(姓氏)
    把开卡的种类统计出来
"""
listvar = [
    {name":彭云飞age":18,1)">money":10000},{夏圣钦":19,1)">":5100陈正正":20,1)">":4800王添龙":21,1)">":2000万潇阳":20}
]

 常规写法
setvar = set()
 listvar:
    if 18 <= i["] <= 21 and  5000 <= i["] <= 5500:
        res = 尊贵VIP卡老" + i[][0]
    else普通用户卡老][0]
    setvar.add(res)
(setvar)

 改写成集合推导式 {三元运算符 + 推导式}
setvar = { "][0] "] <= 5500 else  listvar }
print(setvar)

字典推导式

1.enumerate

功能:

  枚举 ; 将索引号iterable中的值,一个一个拿出来配对组成元组放入迭代器中
参数:

  iterable: 可迭代性数据 (常用:迭代器,容器类型数据,可迭代对象range)
  start: 可以选择开始的索引号(默认从0开始索引)
返回值:迭代器

enumerate形成字典推导式示例:

from collections import Iterator
lst = [东邪西毒南帝北丐]

 基本使用
it = enumerate(lst)  [(0,'东邪'),(1,'西毒'),(2,'南帝'),(3,'北丐')]
(isinstance(it,Iterator))

 for + next
in range(4):
    (next(it))
 list
start可以指定开始值,默认是0
it = enumerate(lst,start=1)
print(list(it))  [(1,(4,'北丐')]

 enumerate 形成字典推导式 变成字典
dic = { k:v in enumerate(lst,1)">) }
print(dic)  {1: '东邪',2: '西毒',3: '南帝',4: '北丐'}

 dict 强制变成字典
dic = dict(enumerate(lst,1)">))
多个iterable中的值,1)">配对组成元组放入迭代器中

  参数:iterable: 可迭代性数据 (常用:迭代器,可迭代对象range)?

  返回值: 迭代器

  特征:如果找不到对应配对的元素,当前元素会被舍弃

lst1=[Fly1daoHurtMojo]
lst2=[SnowSongGiao]
lst3=[770JieJ]

it = zip(lst1,lst2,lst3)
 [('Fly','Snow','770'),('1dao','Song','JieJ')] zip形成字典推导式 变成字典
lst1=[]
dic={k:v  {'Fly': 'Snow','1dao': 'Song','Hurt': 'Giao'} dict强制变为字典
dic = dict(zip(lst1,lst2))
自定义逻辑的迭代器
2.迭代器和生成器区别:
  迭代器本身是系统内置的.重写不了.而生成器是用户自定义的,可以重写迭代逻辑
3.生成器可以用两种方式创建:
  (1)生成器表达式 (里面是推导式,外面用圆括号)
  (2)生成器函数 (用def定义,里面含有yield)

4.生成器表达式<=>元组推导式

gen = (i*2 yield每次返回时,会记住上次离开时执行的位置,下次在调用生成器,会从上次执行的位置往下走
而return直接终止函数,每次重头调用.
yield 6 和 yield(6) 2种写法都可以 yield 6 更像 return 6 的写法 推荐使用

1.生成器函数的基本语法:

 定义一个生成器函数
def mygen():
    print(111)
    yield 1

    print(222yield 2
    
    print(333yield 3

 初始化生成器函数,返回生成器对象,简称生成器
gen = mygen()  gen是生成器对象(生成器)
print(isinstance(gen,Iterator))  gen是一个迭代器

 使用next调用
res = next(gen)
(res)
res =print(res)

关于生成器函数的执行流程

代码解析:
初始化生成器函数 -> 生成器(通过next调用)
第一次调用生成器
res = next(gen) => print(111) yield 1 保存当前代码状态14行,并将1这个值返回 print(1),等待下一次调用
第二次调用生成器
res = next(gen) => 从上一次保存的状态14行继续向下执行
print(222) yield 2 保存当前代码状态17行,并将2这个值返回 print(2),等待下一次调用
第三次调用生成器
res = next(gen) => 从上一次保存的状态17行继续向下执行
print(333) yield 3 保存当前代码状态20行,并将3这个值返回 print(3),等待下一次调用
第四次调用生成器
因为没有更多yield返回数据了,所以直接报错.

2.send的用法

next和send区别:
next 只能取值
send 不但能取值,还能发送值
send注意点:
第一个 send 不能给 yield 传值 默认只能写None
最后一个yield 接受不到send的发送值
send 是给上一个yield发送值

print(process start)
    res = yield 100
    print(res,1)">内部打印1)
    
    res = yield 200
    内部打印2yield 300
    内部打印3process end)

 初始化生成器函数 -> 生成器
gen = mygen()
 在使用send时,第一次调用必须传递的参数是None(硬性语法),因为第一次还没有遇到上一个yield
'''第一次调用'''
res = gen.send(None) <=> next(gen)
(res)
第二次调用
res = gen.send(101) 第三次调用
res = gen.send(201) 第四次调用,因为没有更多的yield返回数据了,所以StopIteration
res = gen.send(301) print(res)

初始化生成器函数,返回生成器对象
第一次调用时,
print("process start")
res = yield 100 记录当前代码状态81行,返回100,等待下一次调用
res = 100 print(100)

第二次调用时,
把101 发送给上一个yield保存的状态81行 res = 101 从81行继续往下走
print(101,"内部打印1")
res = yield 200 记录当前代码状态84行,返回200,等待下一次调用
res = 200 print(200)

第三次调用时,
把201 发送给上一个yield保存的状态84行 res = 201 从84行继续往下走
print(201,"内部打印2")
res = yield 300 记录当前代码状态87行,返回300,等待下一次调用
res = 300 print(300)

3.yield from?

?将一个可迭代对象变成一个迭代器返回

yield from [Alan]
    
gen =(next(gen))
print(next(gen))

4.示例:用生成器描述斐波那契数列

1 1 2 3 5 8 13 21 34 ... """

yield 1
a,b = b,a+b = 1,1

yield 1
a,2

yield 2
a,a+b = 2,3

yield 3
a,a+b = 3,5

yield 5
....

 mygen(maxlen):
    a,b = 0,1
    i = 0
    while i < maxlen:
        yield b
        a,b = b,a+b
        i+=1
    
 初始化生成器函数 -> 生成器
gen = mygen(10print(next(gen))

?

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读