一、列表推导式
'''通过一行循环判断,遍历一系列数据的方式'''
""" 推导式的语法: val for val in Iterable 三种方式: [val for val in Iterable] {val for val in Iterable} {k:v for k,v in Iterable} """
1、向列表里插入100条数据
# 列表里面需要100条数据 lst = [] for i in range(1,101): lst.append(i) print(lst)
改写成推导式
# 基本语法 lst = [i for i in range(1,101)] print(lst)
2、[1,2,3,4,5] -> [3,6,9,12,15]
lst = [1,2,3,4,5] lst_new = [] for i in lst: res = i * 3 lst_new.append(res) print(lst_new)
改写成推导式
lst = [i*3 for i in lst] print(lst)
3、带有判断条件的单循环推导式 (只能是单项分支,接在for后面)
lst = [1,2,3,4,5,6,7,8] lst_new = [] for i in lst: if i % 2 == 1: lst_new.append(i) print(lst_new)
改写成推导式
# 改写成推导式 lst = [i for i in lst if i % 2 == 1] print(lst)
4、双循环推导式
lst1 = ["李博伦","高云峰","孙致和","葛龙"] lst2 = ["李亚","刘彩霞","刘子豪","刘昕"] # "谁"❤"谁" lst_new = [] for i in lst1: for j in lst2: strvar = i + "❤" + j lst_new.append(strvar) print(lst_new)
改写成推导式
# 改写成推导式 lst = [i + "❤" + j for i in lst1 for j in lst2] print(lst)
5、带有判断条件的多循环推导式
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)
改写成推导式
lst = [ i + "❤" + j for i in lst1 for j in lst2 if lst1.index(i) == lst2.index(j) ] print(lst)
6、推导式练习
""" (1).{'x': 'A', 'y': 'B', 'z': 'C' } 把字典写成x=A,y=B,z=C的列表推导式 (2).把列表中所有字符变成小写 ["ADDD","dddDD","DDaa","sss"] (3).x是0-5之间的偶数,y是0-5之间的奇数 把x,y组成一起变成元组,放到列表当中 (4).使用列表推导式 制作所有99乘法表中的运算 (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]] """
# 常规 dic = {'x': 'A', 'y': 'B', 'z': 'C' } lst = [] for k,v in dic.items(): strvar = k + "=" + v lst.append(strvar) print(lst) # 改写推导式 lst = [k + "=" + v for k,v in dic.items()] print(lst)
lst = ["ADDD","dddDD","DDaa","sss"] lst_new = [] # 常规 for i in lst: lst_new.append(i.lower()) print(lst_new) # 改写推导式 lst = [i.lower() for i in lst ] print(lst)
""" 0 2 4 1 3 5 """ # 方法一 lst = [] for x in range(6): for y in range(6): if x % 2 == 0 and y % 2 == 1: lst.append((x,y)) print(lst) lst = [(x,y) for x in range(6) for y in range(6) if x % 2 == 0 and y % 2 == 1] print(lst) # 方法二 lst = [] for x in range(6): if x % 2 == 0: for y in range(6): if y % 2 == 1: lst.append((x,y)) print(lst) lst = [(x,y) for x in range(6) if x % 2 == 0 for y in range(6) if y % 2 == 1] print(lst)
for i in range(9,0,-1): for j in range(1,i+1): print("{}*{}={:2d} ".format(i,j,i*j),end="") print() lst = ["{}*{}={:2d} ".format(i,j,i*j) for i in range(9,0,-1) for j in range(1,i+1) ] print(lst)
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 外层的循环动的慢,内层的循环动的快, 外层的循环动一次,内层的循环动3次, 利用这个规律取出对应下标,乘积即可. """ lst = [] for i in range(3): for j in range(3): print(i,j) res = M[i][j] * N[i][j] lst.append(res) print(lst) # 改写推导式[效果一] lst = [M[i][j] * N[i][j] for i in range(3) for j in range(3)] print(lst) # 改写推导式[效果二] # 1 . 先遍历出三个空列表 # lst = [ [] for i in range(3) ] => [ [],[],[] ] # 2 . 把空列表中的数据在通过推导式算出所有内容 lst = [ [M[i][j] * N[i][j] for j in range(3)] for i in range(3) ] print(lst) """ 常规写法: M = [[1,2,3],[4,5,6],[7,8,9]] N = [[2,2,2],[3,3,3],[4,4,4]] lst2 = [] for i in range(3): lst = [] for j in range(3): lst.append( M[i][j] * N[i][j] ) lst2.append(lst) print(lst2) """
二、集合推导式
""" 案例: 满足年龄在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":18,"money":20} ]
常规写法
setvar = set() for i in listvar: if 18 <= i["age"] <= 21 and 5000 <= i["money"] <= 5500: res = "尊贵VIP卡老" + i["name"][0] else: res = "抠脚大汉卡老" + i["name"][0] setvar.add(res) print(setvar)
改写成集合推导式
# {三元运算符 + 推导式} setvar = { "尊贵VIP卡老" + i["name"][0] if 18 <= i["age"] <= 21 and 5000 <= i["money"] <= 5500 else "抠脚大汉卡老" + i["name"][0] for i in listvar } print(setvar)
三、字典推导式
""" enumerate(iterable,[start=0]) 功能:枚举 ; 将索引号和iterable中的值,一个一个拿出来配对组成元组放入迭代器中 参数: iterable: 可迭代性数据 (常用:迭代器,容器类型数据,可迭代对象range) start: 可以选择开始的索引号(默认从0开始索引) 返回值:迭代器 """
from collections import Iterator lst = ["东邪","西毒","南帝","北丐"] # 基本使用 it = enumerate(lst) print(isinstance(it,Iterator))
for + next
# for + next for i in range(4): print(next(it)) # (0, '东邪') # (1, '西毒') # (2, '南帝') # (3, '北丐')
list
"""start可以指定开始值,默认是0""" it = enumerate(lst,start=1) print(list(it)) #[(1, '东邪'), (2, '西毒'), (3, '南帝'), (4, '北丐')]
enumerate 形成字典推导式 变成字典
dic = { k:v for k,v in enumerate(lst,start=1) } print(dic) # {1: '东邪', 2: '西毒', 3: '南帝', 4: '北丐'}
dict 强制变成字典
dic = dict(enumerate(lst,start=1)) print(dic) # {1: '东邪', 2: '西毒', 3: '南帝', 4: '北丐'}
四、zip
""" zip(iterable, ... ...) 功能: 将多个iterable中的值,一个一个拿出来配对组成元组放入迭代器中 iterable: 可迭代性数据 (常用:迭代器,容器类型数据,可迭代对象range) 返回: 迭代器 特征: 如果找不到对应配对的元素,当前元素会被舍弃 """
# 基本使用 lst1 = ["aa","bb","cc","dd"] lst2 = ["qq","ww","ee"] lst3 = ["zz","xx"] # it = zip(lst1,lst2) it = zip(lst1,lst2,lst3) print(isinstance(it,Iterator)) print(list(it)) """ True [('aa', 'qq'), ('bb', 'ww'), ('cc', 'ee')] [('aa', 'qq', 'zz'), ('bb', 'ww', 'xx')] """
1、zip 形成字典推导式 变成字典
lst1 = ["晏国彰","刘子涛","郭凯","宋云杰"] lst2 = ["刘有右柳翔","冯雍","孙志新"] dic = { k:v for k,v in zip(lst1,lst2) } print(dic) # dict 强制变成字典 dic = dict(zip(lst1,lst2)) print(dic)
五、生成器表达式
""" #生成器本质是迭代器,允许自定义逻辑的迭代器 #迭代器和生成器区别: 迭代器本身是系统内置的.重写不了.而生成器是用户自定义的,可以重写迭代逻辑 #生成器可以用两种方式创建: (1)生成器表达式 (里面是推导式,外面用圆括号) (2)生成器函数 (用def定义,里面含有yield) """
from collections import Iterator,Iterable # 生成器表达式 gen = (i*2 for i in range(1,11)) print(isinstance(gen,Iterator)) # next res = next(gen) print(res) # for for i in gen: print(i) # for + next gen = (i*2 for i in range(1,11)) for i in range(3): res = next(gen) print(res) # list print("<=====>") res = list(gen) print(res)
六、生成器函数
""" # yield 类似于 return 共同点在于:执行到这句话都会把值返回出去 不同点在于:yield每次返回时,会记住上次离开时执行的位置 , 下次在调用生成器 , 会从上次执行的位置往下走 而return直接终止函数,每次重头调用. yield 6 和 yield(6) 2种写法都可以 yield 6 更像 return 6 的写法 推荐使用 """
1、生成器函数的基本语法
# 定义一个生成器函数 def mygen(): print(111) yield 1 print(222) yield 2 print(333) yield 3 # 初始化生成器函数,返回生成器对象,简称生成器 gen = mygen() print(isinstance(gen,Iterator)) # 使用next调用 res = next(gen) print(res) res = next(gen) print(res) res = next(gen) print(res) # res = next(gen) error # 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、代码优化
def mygen(): for i in range(1,101): yield "该球衣号码是{}".format(i) # 初始化生成器函数 -> 生成器 gen = mygen() # for + next 调用数据 for i in range(50): res = next(gen) print(res) print("<====>") for i in range(30): res = next(gen) print(res)
3、send用法
""" ### send # next和send区别: next 只能取值 send 不但能取值,还能发送值 # send注意点: 第一个 send 不能给 yield 传值 默认只能写None 最后一个yield 接受不到send的发送值 send 是给上一个yield发送值 """
def mygen(): print("process start") res = yield 100 print(res,"内部打印1") res = yield 200 print(res,"内部打印2") res = yield 300 print(res,"内部打印3") print("process end") # 初始化生成器函数 -> 生成器 gen = mygen() # 在使用send时,第一次调用必须传递的参数是None(硬性语法),因为第一次还没有遇到上一个yield '''第一次调用''' res = gen.send(None) #<=> next(gen) print(res) '''第二次调用''' res = gen.send(101) #<=> next(gen) print(res) '''第三次调用''' res = gen.send(201) #<=> next(gen) print(res) '''第四次调用, 因为没有更多的yield返回数据了,所以StopIteration'''
""" # 代码解析: 初始化生成器函数,返回生成器对象 第一次调用时, 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) """
4、yield from : 将一个可迭代对象变成一个迭代器返回
def mygen(): yield from ["马生平","刘彩霞","余锐","晏国彰"] gen = mygen() print(next(gen)) print(next(gen)) print(next(gen)) print(next(gen))
5、用生成器描述斐波那契数列
"""1 1 2 3 5 8 13 21 34 ... """ """ yield 1 a,b = b,a+b = 1,1 yield 1 a,b = b,a+b = 1,2 yield 2 a,b = b,a+b = 2,3 yield 3 a,b = b,a+b = 3,5 yield 5 .... """ def mygen(maxlen): a,b = 0,1 i = 0 while i < maxlen: yield b a,b = b,a+b i+=1 # 初始化生成器函数 -> 生成器 gen = mygen(10) for i in range(3): print(next(gen))
七、练习
""" 者 创建于 4天前 # 1.用推导式写如下程序 (1)构建如下列表:[0, 2, 4, 6, 8, 10, 12, 14, 16, 18] (2)lst = ['alex', 'WuSir', '老男孩', '神秘男孩'] 将lst构建如下列表:['alex0', 'WuSir1', '老男孩2', '神秘男孩3'] (3)构建如下列表:[(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 6)] (4)求出50以内能被3整除的数的平方,并放入到一个列表中。 (5)M = [[1,2,3],[4,5,6],[7,8,9]], 把M中3,6,9组成新列表 (6)构建如下列表:['python1期', 'python2期', 'python3期', 'python4期', 'python6期', 'python7期', 'python8期', 'python9期', 'python10期'] (7)过滤掉长度小于3的字符串列表 , 并转换成大写字母 (8)除了大小王,里面有52项,每一项是一个元组,请返回如下扑克牌列表[('红心','2'),('草花','J'), …('黑桃','A')] # 2.用推导式写如下程序 lst1 = { 'name':'alex', 'Values':[ {'timestamp': 1517991992.94,'values':100,}, {'timestamp': 1517992000.94,'values': 200,}, {'timestamp': 1517992014.94,'values': 300,}, {'timestamp': 1517992744.94,'values': 350}, {'timestamp': 1517992800.94,'values': 280} ] } 将lst1 转化成如下lst2: lst2 = [ [1517991992.94, 100], [1517992000.94, 200], [1517992014.94, 300], [1517992744.94, 350], [1517992800.94, 280] ] # 3.读取一个文件所有内容,通过生成器调用一次获取一行数据. # 4.将普通求和函数改写成yield写法 def add(a,b): return a + b """
print([i * 2 for i in range(10)])
print([j + str(i) for i in range(4) for j in lst if i == lst.index(j)])
print([(i, i + 1) for i in range(6)])
print([i * i for i in range(50) if i % 3 == 0])
# 方法一 print([j for i in m for j in i if i.index(j) == 2]) # 方法二- print([i[2] for i in m])
print(['python' + str(i) + '期' for i in range(1, 11)])
lst = ['41', 'ra', 'da', '456', 'das'] print([i.upper() for i in lst if len(i) >= 3])
lst = ['红心', '红桃', '黑桃', '草花'] print([(i, j) for j in range(1, 14) for i in lst])
lst1 = { 'name':'alex', 'Values':[ {'timestamp': 1517991992.94,'values':100,}, {'timestamp': 1517992000.94,'values': 200,}, {'timestamp': 1517992014.94,'values': 300,}, {'timestamp': 1517992744.94,'values': 350}, {'timestamp': 1517992800.94,'values': 280} ] } ret = [[lst1['Values'][i]['timestamp'],lst1['Values'][i]['values']] for i in range(5)] print(ret)
with open('1.txt',mode='r+',encoding='utf-8') as f: res = f.readlines() print(res) def func1(): for i in range(len(res)): yield res[i] ret = func1() print(next(ret)) print(next(ret)) print(next(ret))
def add(a,b): yield a+b res = add(1,2) print(res.__next__())
# 第1题 def func(): return [lambda x : i*x for i in range(4)] res = [m(2) for m in func()] print(res)
# (1) 1号正确 [lambda x : i*x for i in range(4)] # (2) 不存在的 # [ lambda x : i*x for i in range(4) ] # def func(x): # return i*x for i in range(4) # func(10) # def func(x): # return [i*x for i in range(4)] # lst = i for i in range(10) def func(): return [lambda x : i*x for i in range(4)] def func(): lst = [] for i in range(4): # 定义函数 def func2(x): return i*x lst.append(func2) return lst # lst = func() # print(lst) """ [<function func.<locals>.func2 at 0x0000014F4FCE3E18>, <function func.<locals>.func2 at 0x0000014F4FCE3C80>, <function func.<locals>.func2 at 0x0000014F4FCE3D08>, <function func.<locals>.func2 at 0x0000014F4FCE3D90> ] (1) 在定义函数的时候,不会去执行函数当中的代码块,只有在调用函数的时,才执行. (2) i这个变量被闭包函数func2使用 生命周期被延长了,暂时不释放,当调用时,i此刻为3,直接调用. """ # 在遍历列表时候,分别拿出4个函数,进行调用m(2) res = [m(2) for m in func()] # 6 6 6 6 # func2(2) 0*2 1 * 2 2 * 2 3*2 print(res,"<===>") for i in range(4): print(i) # for循环遍历结束时 , i = 3 print(i)
# 第2题 def add(a,b): #普通求和函数 return a + b def test(): #生成器函数 for i in range(4): yield i g=test() for n in [2,10]: g=(add(n,i) for i in g) print(list(g))
# 第2题 def add(a,b): #普通求和函数 return a + b def test(): #生成器函数 for i in range(4): yield i g=test() for n in [2,10]: # (1) 生成器表达式 (2) 生成器函数 g=(add(n,i) for i in g) # print(list(g)) # (1) 等循环结束之后,在打印n,结果是10 print("<====>") for n in [2,10]: print(n) print(n) # (2) 循环里面定义了2次生成器 # 第一次 g=(add(n,i) for i in g) # g = (0,1,2,3) n=10 g = (10 11 12 13) # 第二次 g=(add(n,i) for i in g) # g = (10,11,12,13) n=10 g = (20,21,22,23) [20,21,22,23] """ 定义生成器,里面的代码时不执行的 只有在调用生成器的时候,里面的代码才执行 for / for + next / next / list """