生成器,生成器表达式,列表推导式,内置函数I
程序员文章站
2022-04-15 15:56:37
1. 内容大纲 1. 生成器 yield yield与 return send方法(了解) yield 与 yield from 2. 生成器表达式,列表推导式 3. 内置函数 I 2. 具体内容: 生成器 生成器:python社区,生成器与迭代器看成是一种。生成器的本质就是迭代器。唯一的区别:生成 ......
-
内容大纲
-
生成器
- yield
- yield与 return
- send方法(了解)
- yield 与 yield from
生成器表达式,列表推导式
内置函数 i
-
-
具体内容:
-
生成器
- 生成器:python社区,生成器与迭代器看成是一种。生成器的本质就是迭代器。唯一的区别:生成器是需要我们自己用python代码构建的数据结构。迭代器都是python给你提供的已经写好的工具或者通过数据转化得来的(比如文件句柄,iter([1,2,3])。
- 创建(获取)生成器的三种方式:
- 通过生成器函数。
- 通过生成器表达式。
- python内置函数或者模块提供
- 创建(获取)生成器的三种方式:
- 生成器函数获得生成器:
函数: def func(): print(111) print(222) return 3 ret = func() print(ret) 111 222 3 生成器函数也叫生成器,通过生成器函数构建生成器: def func(): print(11) yield 22 yield 33 ret = func() #获取生成器对象 print(ret) # <generator object func at 0x000002003a91b1a8> #generator 生成器 next(ret) # 11 next让指针停留在第一个yield后面。生成器取值但未打印 print(next(ret)) # 33 生成器取值 生成器的本质就是迭代器.迭代器如何取值,生成器就如何取值:next会获取对应yield生成的元素。一个yield对应一个next,next超过yield数量(最后⼀个yield执⾏完毕. 再次next),就会报错 def func(): print(111) print(222) yield 3 a = 1 b = 2 c = a + b print(c) yield 4 ret = func() print(ret)#<generator object func at 0x000001d73472b1a8> print(next(ret))#next让指针停留在第一个yield后面。一个next对应一个yield # 111 # 222 # 3 print(next(ret))#保留了上次的位置,从第一个yield后面开始执行,最终next让指针停留在第二个yield后面。一个next对应一个yield # 3 # 4
-
yield 与 return的区别:
return:一般在函数中只设置一个,它的作用是终止函数,并且给函数的执行者返回值。 yield:只要函数中有yield,那么这个函数就是一个生成器函数(生成器),而不是函数了。在执行这个函数的时候.就不再是函数的执行了.而是获取这个生成器对象。 yield:在生成器函数中可设置(存在)多个yield.,yield不会结束生成器函数,一个yield对应一个next。
-
吃包子练习题:
#非常直观,但占用内存 def func(): l1 =[] for i in range(1,5001): l1.append(f'{i}号包子') return l1 ret = func() print(ret) #非常的节省内存,而且还可以保留上次的位置 def gen_func(): for i in range(1,5001): yield f'{i}号包子' ret = gen_func() print(ret)#<generator object gen_func at 0x0000016ad3d1b1a8> for i in range(200): #从1号包子到200号包子 print(next(ret)) for i in range(300): #从201号包子到500号包子,多次next包子的号码是按照顺序记录的。 print(next(ret))
-
send方法(了解)
# next只能获取yield生成的值,但是不能传递值 def gen(name): print(f'{name} ready to eat') while 1: food = yield print(f'{name} start to eat {food}') dog = gen('alex') next(dog) #alex ready to eat 第一次next让指针停留在第一个yield后面 next(dog) #alex start to eat none 能记住上次的位置,再次执行从yield后面开始执行,最后又停在yield后面 next(dog) #alex start to eat none 同上 #send不仅能获取yield生成的值,还能传递值 def gen(name): print(f'{name} ready to eat') while 1: food = yield 222 print(f'{name} start to eat {food}') dog = gen('alex')##获取生成器对象 next(dog) # alex ready to eat 第一次必须用next让指针停留在第一个yield后面 ret = dog.send('骨头')#alex start to eat 骨头 print(ret)#222 # 与next一样,可以获取到yield的值 def gen(name): print(f'{name} ready to eat') while 1: food = yield print(f'{name} start to eat {food}') dog = gen('alex') next(dog)#alex ready to eat # 可以给上一个yield发送值 dog.send('骨头')#alex start to eat 骨头 dog.send('狗粮')#alex start to eat 狗粮 dog.send('香肠')#alex start to eat 香肠 send 和 next()区别: 相同点: send 和 next()都可以让生成器对应的yield向下执行一次。 都可以获取到yield生成的值。 不同点: 第一次获取yield值只能用next不能用send(可以用send(none))。 send可以给上一个yield置传递值。'''
-
yield 与 yield from
yield from:可以直接把可迭代对象中的每一个数据作为生成器的结果进行返回 def func(): l1 = [1,2,3,4,5] yield l1 ret = func() print(ret)#<generator object func at 0x00000162756fb1a8> print(next(ret))#[1, 2, 3, 4, 5] def func(): lst = ['卫龙','老冰棍','北冰洋','牛羊配'] yield lst ret = func() print(ret)#<generator object func at 0x000001b7a853b0f8> print(next(ret)) # 只是返回一个列表['卫龙', '老冰棍', '北冰洋', '牛羊配'] 【面试题】 def func(): lst = ['卫龙','老冰棍','北冰洋','牛羊配'] yield from lst #将lst这个列表变成了迭代器返回,它会将这个可迭代对象(列表)的每个元素当成迭代器的每个结果进行返回。 ''' yield from lst 相当于下面的: yield '卫龙' yield '老冰棍' yield '北冰洋' yield '牛羊配' ''' ret = func() print(ret)# <generator object func at 0x0000026314efb0f8> print(next(ret)) #卫龙 print(next(ret)) #老冰棍 print(next(ret)) #北冰洋 print(next(ret)) #牛羊配 def func(): l1 = [1, 2, 3, 4, 5] yield from l1 ret = func() for i in range(5): print(next(ret)) #有个小坑, yield from 是将列表中的每一个元素返回, 所以如果写两个yield from 并不会产生交替的效果 def func(): lst1 = ['卫龙', '老冰棍', '北冰洋', '牛羊配'] lst2 = ['馒头', '花卷', '豆包', '大饼'] yield from lst1 yield from lst2 g = func() for i in g: print(i) # 卫龙 # 老冰棍 # 北冰洋 # 牛羊配 # 馒头 # 花卷 # 豆包 # 大饼
- 生成器:python社区,生成器与迭代器看成是一种。生成器的本质就是迭代器。唯一的区别:生成器是需要我们自己用python代码构建的数据结构。迭代器都是python给你提供的已经写好的工具或者通过数据转化得来的(比如文件句柄,iter([1,2,3])。
-
生成器表达式,列表推导式
-
用一行代码构建一个比较复杂有规律的列表。
l1 = [] for i in range(1,11): l1.append(i) print(l1)#[1, 2, 3, 4, 5, 6, 7, 8, 9, 10] #列表推导式: l1 = [i for i in range(1,11)] print(l1)#[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
字典推导式(了解) lst1 = ['jay', 'jj', 'meet'] lst2 = ['周杰伦','林俊杰','元宝'] dic = { lst2[i]: lst1[i] for i in range(len(lst1))} print(dic)#{'周杰伦': 'jay', '林俊杰': 'jj', '元宝': 'meet'} 集合推导式(了解) print({i for i in range(1,11)})
-
列表推导式:
缺点: 1,有毒。列表推导式只能构建比较复杂并且有规律的列表。 不要太着迷。 2,超过三层循环才能构建成功的,就不建议用列表推导式。 3,查找错误(debug模式)不行 优点: 一行构建,简单。
-
循环模式:[变量(加工后的变量) for 变量 in iterable]
# 将10以内所有整数的平方写入列表。 ret = [i**2 for i in range(1,11)] print(ret) # 100以内所有的偶数写入列表. print([i for i in range(2, 101, 2)]) # 从python1期到python100期写入列表lst print([f'python{i}期' for i in range(1,101)]) #【*】一行代码构建[2, 3, 4, 5, 6, 7, 8, 9, 10, 'j', 'q', 'k', 'a'] l1 = [i for i in range(2,11)] + list('jqka') print(l1)#[2, 3, 4, 5, 6, 7, 8, 9, 10, 'j', 'q', 'k', 'a']
-
筛选模式:[变量(加工后的变量) for 变量 in iterable if 条件]
# 30以内能被3整除的数 l1 = [i for i in range(1,31) if i%3 == 0] print(l1) # 过滤掉长度小于3的字符串列表,并将剩下的转换成大写字母 l1 = ['barry', 'ab', 'alex', 'wusir', 'xo'] print([i.upper() for i in l1 if len(i) >= 3 ]) # 含有两个'e'的所有的人名全部大写留下来 names = [['tom', 'billy', 'jefferson', 'andrew', 'wesley', 'steven', 'joe'],['alice', 'jill', 'ana', 'wendy', 'jennifer', 'sherry', 'eva']] 1.正常做法: l1 = [] for i in names: for j in i: if j.count('e') == 2: l1.append(j) print(l1)#['jefferson', 'wesley', 'steven', 'jennifer'] 2.列表推导式 print([j for i in names for j in i if j.count('e') == 2 ])# ['jefferson', 'wesley', 'steven', 'jennifer']
-
生成器表达式: 列表推导式与生成器表达式区别。 1.写法上: [] () 2.iterable:可迭代对象 iterator:迭代器 生成器表达式和列表推导式的区别: 1.列表推导式比较耗内存,所有数据一次性加载到内存。而生成器表达式遵循迭代器协议,逐个产生元素。 2.得到的值不一样,列表推导式得到的是一个列表。生成器表达式获取的是一个生成器。 3.列表推导式一目了然,生成器表达式只是一个内存地址。
与列表推导式的写法几乎一模一样,也有筛选模式,循环模式,多层循环构建。写法上只有一个不同:[] 换成 (). print([i for i in range(1,11)]) #列表推导式 print((i for i in range(1,11))) #生成器表达式 obj = (i for i in range(1,11)) print(next(obj)) print(next(obj)) print(next(obj)) print(next(obj)) print(next(obj)) #或者: for i in obj: print(i)
-
-
内置函数 i
#eval:执行字符串类型的代码,并返回最终结果。 eval('2 + 2') # 4 n = 81 eval("n + 4") # 85 eval('print(666)') # 666 eval 剥去字符串的外衣运算里面的代码,有返回值。网络传输的str input 输入的时候,sql注入等等绝对不能使用eval。 s1 = '1 + 3' print(s1)# 1 + 3 print(eval(s1)) #4 ** s = '{"name": "alex"}' print(s,type(s))#{"name": "alex"} <class 'str'> print(dict(s)) # 不行 print(eval(s),type(eval(s)))#{'name': 'alex'} <class 'dict'> #exec: 执行字符串类型的代码。 exec 与eval几乎一样, 处理代码流 s = ''' for i in [1,2,3]: print(i) ''' exec(s) msg = """ for i in range(10): print(i) """ print(msg) #for i in range(10): #print(i) exec(msg) 0-9 eval(msg)#报错 #hash:获取一个对象(可哈希对象:int,str,bool,tuple)的哈希值。hash只能操作不可变数据类型。 print(hash(12322)) print(hash('123')) print(hash('arg')) print(hash('alex')) print(hash(true)) print(hash(false)) print(hash((1, 2, 3))) print(hash('fsjkdafsda')) #help:函数用于查看函数或模块用途的详细说明。 print(help(list)) print(help(str.split)) s1 = 'fjdsls' print(help(str)) print(help(str.upper)) s1 = 'sfsda' s1.upper() #callable:函数用于检查一个对象是否是可调用的。如果返回true,object仍然可能调用失败;但如果返回false,调用对象ojbect绝对不会成功。 name = 'alex' def func(): pass print(callable(name)) # false print(callable(func)) # true #int:函数用于将一个字符串或数字转换为整型。 print(int()) # 0 print(int('12')) # 12 print(int(3.6)) # 3 print(int('0100', base=2)) # 将2进制的 0100 转化成十进制。结果为 4 #float:函数用于将整数和字符串转换成浮点数。 print(float(3)) # 3.0 #complex:函数用于创建一个值为real + imag * j的复数或者转化一个字符串或数为复数。如果第一个参数为字符串,则不需要指定第二个参数。。 print(complex(1, 2)) # (1+2j) #bin:将十进制转换成二进制并返回。 #oct:将十进制转化成八进制字符串并返回。 #hex:将十进制转化成十六进制字符串并返回。 print(bin(10), type(bin(10))) # 0b1010 <class 'str'> print(oct(10), type(oct(10))) # 0o12 <class 'str'> print(hex(10), type(hex(10))) # 0xa <class 'str'> #divmod:计算除数与被除数的结果,返回一个包含商和余数的元组(a // b, a % b)。 #round:保留浮点数的小数位数,默认保留整数。 #pow:求x ** y次幂。(三个参数为x ** y的结果对z取余) print(divmod(7, 2)) # (3, 1) print(round(7 / 3, 2)) # 2.33 print(round(7 / 3)) # 2 print(round(3.32567, 3)) # 3.326 print(pow(2, 3)) # 两个参数为2**3次幂 print(pow(2, 3, 3)) # 三个参数为2**3次幂,对3取余。 #bytes:用于不同编码之间的转化。 s = '你好' bs = s.encode('utf-8') print(bs) s1 = bs.decode('utf-8') print(s1) bs = bytes(s,encoding='utf-8') print(bs) b = '你好'.encode('gbk') b1 = b.decode('gbk') print(b1.encode('utf-8')) # ord 输入字符找该字符编码的位置 print(ord('a')) print(ord('中')) # chr 输入位置数字找出其对应的字符 print(chr(97)) print(chr(20013)) #repr: 返回一个对象的string形式(原形毕露)。 # %r 原封不动的写出来 name = 'taibai' print('我叫%r'%name) # repr 原形毕露 print(repr('{"name":"alex"}')) print('{"name":"alex"}') # all 可迭代对象中,全都是true才是true # any 可迭代对象中,有一个true 就是true print(all([1,2,true,0])) print(any([1,'',0]))
-
-
总结
- 生成器:***
- 生成器函数 yield
- yield与return 区别。yield from
- 列表推导式,生成器表达式。 ***
- 内置函数:内置函数