Flask接口签名sign原理与实例代码浅析
328
2022-08-25
python--迭代器、isinstance、生成器、send(Python生成器和迭代器)
迭代器
isinstance(对象, 类型) 判断xx对象是否是xxx类型的
from collections import Iterable # 可迭代的from collections import Iterator # 迭代器
判断列表 [1,2,3] 是不是可迭代的
lst = [1, 2, 3]print(isinstance(lst, list))
结果
True # 可迭代的
可迭代对象(Iterable):内部包含__iter__().迭代器(Iterator): 内部含有__iter__() __next__()dir()来查看一个对象,数据类型中包含了哪些东西迭代器里面一定有__next__(), __iter__()判断是否是可迭代的 迭代器一定是可迭代的
str, list, tuple, set, dictf, range都是可迭代的,int不是可迭代的,如果执行for i in 123:会报错'int' object is not iterable
迭代器的特点:
省内存惰性机制(__next__一个出来一个)只能往后拿,不能往前拿
lst = [1, 2, 3]s = "王尼玛"print("__iter__" in dir(s)) # 可迭代的print("__iter__" in dir(lst)) # 可迭代的print("__iter__" in dir(123)) # 不可迭代的
结果:
TrueTrueFalse
list是一个Iterable.可迭代的
lst = ["皇阿玛", "皇额娘", "容嬷嬷", "紫薇"]# 获取迭代器it = lst.__iter__()# 迭代器往外拿元素. __next__()print(it.__next__()) # 皇阿玛print(it.__next__()) # 皇额娘print(it.__next__()) # 容嬷嬷print(it.__next__()) # 紫薇print(it.__next__()) # 迭代到最后一个元素之后. 再进行迭代就报错了 StopIteration
结果:
皇阿玛皇额娘容嬷嬷紫薇# 还有个报错
lst = [1, 2, 3]from collections import Iterable # 可迭代的from collections import Iterator # 迭代器print(isinstance(lst, Iterable))print(isinstance(lst, Iterator))print(isinstance(lst, list))
结果:
TrueFalseTrue
生成器
生成器的本质就是迭代器
生成器的三种创建办法:
通过生成器函数通过生成器表达式创建生成器通过数据转换
生成器函数:
函数中包含了yield的就是生成器函数注意:生成器函数被执行. 获取到的是生成器. 而不是函数的执行
生成器表达式:
(结果 for 变量 in 可迭代对象 if 筛选)
取值:
__next__()send(值) 给上一个yield位置传一个值, 第一个和最后一个yield不用传值可以for循环list(g)
通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。
所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器:generator。
import timedef func(): sum = 0 print('in the func...') while 1: yield sumf = func() # 并不会执行func函数print('abc')time.sleep(20)print(f.__next__())
结果:
abcin the func...0
只有遇到__next__时才会执行函数,这是生成器的惰性机制造成的。
def func(): print("我是周杰伦") yield "昆凌" # 函数中包含了yield, 当前这个函数就不再是普通的函数了. 是生成器函数 print("我是王力宏") yield "李云迪???" print("我是笛卡尔积") yield "笛卡尔积是谁" print("你好啊") # 最后一个yield之后如果再进行__next__()会报错g = func() # 通过函数func()来创建一个生成器,生成器的本质是迭代器. 迭代器可以被迭代 生成器可以直接for循环print(g)print(g.__next__())print(g.__next__())
结果:
return 直接返回结果. 结束函数的调用
yield 返回结果.可以让函数分段执行
要创建一个generator,有很多种方法。第一种方法很简单,只要把一个列表生成式的[]改成(),就创建了一个generator:
print((i*2 for i in
结果:
只是返回了生成器的内存对象,没有调用,就没有生成
a = (i * 2 for i in range(4))for i in a: print(i)
结果:
0246
a = (i * 2 for i in range(4))print(a.__next__())print(a.__next__())print(a.__next__())
结果:
024
只记录当前的位置,只有一个__next__()方法
生成者和消费者
import timedef consumer(name): print("%s 准备吃包子啦!" % name) while True: baozi = yield # 停止,下面的代码先不执行 print("包子[%s]来了,被[%s]吃了!" % (baozi, name))def producer(name): c = consumer('A') c2 = consumer('B') c.__next__() c2.__next__() print("老子开始准备做包子啦!") for i in range(5): time.sleep(1) print("做了2个包子!") c.send(i) # 跳到yield,执行下面的代码 c2.send(i)producer("zou")
结果:
A 准备吃包子啦!B 准备吃包子啦!老子开始准备做包子啦!做了2个包子!包子[0]来了,被[A]吃了!包子[0]来了,被[B]吃了!做了2个包子!包子[1]来了,被[A]吃了!包子[1]来了,被[B]吃了!做了2个包子!包子[2]来了,被[A]吃了!包子[2]来了,被[B]吃了!做了2个包子!包子[3]来了,被[A]吃了!包子[3]来了,被[B]吃了!做了2个包子!包子[4]来了,被[A]吃了!包子[4]来了,被[B]吃了!
send
next__() 可以让生成器向下执行一次
send() 也可以让生成器向下执行一次, 给上一个yield传一个值, 第一个不能用send(). 最后一个也不要传值
def func(): print("大碴粥") a = yield "11" print(a) print("狗不理") b = yield "22" print(b) print("大麻花") yield "33"g = func()print(g.__next__())print(g.send(1))print(g.send(2))
结果:
大碴粥111狗不理222大麻花33
代码分析:
执行print(g.__next__()),执行到yield "11"结束,左边的a=yield "11"没有执行,因为赋值运算先执行右边的,而生成器遇到yield就停止。这句print(g.send(1))执行a=yield "11"左边的,也就是把send里面的值1赋值给了a,然后到 yield "22"结束
def eat(): print("我吃什么啊") a = yield "馒头" print("a=", a) b = yield "大饼" print("b=", b) c = yield "韭菜盒子" print("c=", c) yield "GAME OVER"gen = eat() # 获取⽣成器ret1 = gen.__next__()print(ret1)ret2 = gen.send("胡辣汤")print(ret2)ret3 = gen.send("狗粮")print(ret3)ret4 = gen.send("猫粮")print(ret4)
结果:
我吃什么啊馒头a= 胡辣汤大饼b= 狗粮韭菜盒子c= 猫粮GAME OVER
def func(): yield 11 yield 22 yield 33 yield 44g = func()lst = list(g) # 可迭代对象print(lst)
结果:
[11, 22, 33, 44]
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~