fromcollectionsimportIterable,Iteratora=[,2,3]print(isinstance(a,Iterator))print(isinstance(a,Iterable))
返回结果:
FalseTrue
fromcollectionsimportIterable,Iteratora=[,2,3]a=iter(a)print(isinstance(a,Iterator))print(isinstance(a,Iterable))print(next(a))print(----)forxina:print(x)
返回结果:
TrueTrue----23
classs:def__init__(self,x):self.x=xdef__iter__(self):returniter(self.x)#这里必须要返回一个可以迭代的对象#def__getitem__(self,item):#returnself.x[item]#iter和getitem其中必须要实现一个a=s(23)#这里的a就是可迭代对象#这里不能调用next(a)方法,因为没有定义forxina:print(x)
这里把注释符去掉返回结果也是一样的,返回结果:
23迭代器对象
一开始提起,iter搭配Iterable做可迭代对象,next搭配Iterator做迭代器。next()接受一个迭代器对象,作用是获取迭代器对象的下一个值,迭代器是用来做迭代的,只会在需要的时候产生数据。
和可迭代对象不同,可迭代对象一开始是把所有的列表放在一个变量中,然后用getitem方法不断的返回数值,getitem中的item就是索引值。
但是next方法并没有索引值,所以需要自己维护一个索引值,方便获取下一个变量的位置。
classs:def__init__(self,x):self.x=x#获取传入的对象self.index=0#维护索引值def__next__(self):try:result=self.x[self.index]#获取传入对象的值exceptIndexError:#如果索引值错误raiseStopIteration#抛出停止迭代self.index+=#索引值+,用来获取传入对象的下一个值returnresult#返回传入对象的值a=s([,2,3])print(next(a))print(----------)forxina:#类中并没有iter或者getitem魔法函数,不能用for循环,会报错print(x)
返回结果:
Traceback(mostrecentcalllast):----------File"C:/CODE/Python进阶知识/迭代协议/迭代器.py",line34,inmoduleforxina:TypeError:sobjectisnotiterable
classs:def__init__(self,x):self.x=x#获取传入的对象self.index=0#维护索引值def__next__(self):try:result=self.x[self.index]#获取传入对象的值exceptIndexError:#如果索引值错误raiseStopIteration#抛出停止迭代self.index+=#索引值+,用来获取传入对象的下一个值returnresult#返回传入对象的值def__iter__(self):returnselfa=s([,2,3])print(next(a))print(----------)forxina:print(x)
返回结果:
----------23
classs:def__init__(self,x):self.x=xself.index=0def__next__(self):try:result=self.x[self.index]exceptIndexError:raiseStopIterationself.index+=returnresultclassb:def__init__(self,x):self.x=xdef__iter__(self):returns(self.x)a=b([,2,3])forxina:print(x)
返回结果:
23
classs:def__init__(self,x):self.x=x#获取传入的对象self.index=0#维护索引值def__next__(self):try:result=self.x[self.index]#获取传入对象的值exceptIndexError:#如果索引值错误raiseStopIteration#抛出停止迭代self.index+=#索引值+,用来获取传入对象的下一个值returnresult#返回传入对象的值#def__iter__(self):#returnselfclassb(s):def__init__(self,x):self.x=xself.index=0def__iter__(self):returns(self.x)a=b([,2,3])print(next(a))print(next(a))
返回结果:
2
defgen():yield#返回一个对象,这个对象的值是defret():return#返回一个数字g=gen()r=ret()print(g,r)print(next(g))
返回结果:
generatorobjectgenat0xFDA2D58
defgen():yieldyieldyieldyieldyieldyield#返回一个对象,这个对象内的值是和,...defret():returnreturn3#第二个return是无效的g=gen()r=ret()print(g,r)print(next(g))forxing:print(x)
返回结果:
generatorobjectgenat0xFE32D58
importdis#查看函数程序字节码a=langziprint(dis.dis(a))print(-*20)defsb(admin):print(admin)print(dis.dis(sb))
返回结果:
0LOAD_NAME0(lzngzi)#加载名字为langzi2RETURN_VALUE#返回值None--------------------50LOAD_GLOBAL0(print)#加载一个print函数2LOAD_FAST0(admin)#加载传递参数为admin4CALL_FUNCTION#调用这个函数6POP_TOP#从栈的顶端把元素移除出来8LOAD_CONST0(None)#因为该函数没有返回任何值,所以加载的值是none0RETURN_VALUE#最后把load_const的值返回(个人理解)None
代码函数运行的时候,python将代码编译成字节码,当函数存在yield的时候,python会将这个函数标记成生成器,当调用这个函数的时候,会返回生成器对象,调用这个生成器对象后C语言中写的函数会记录上次代码执行到的位置和变量。
再C语言中的PyGenObject中有两个值,gi_frame(存储上次代码执行到的位置f_lasti的上次代码执行到的变量f_locals),gi_code(存储代码),使用dis也可以获取到上次代码执行的位置和值。
举个例子:
importdisdefgen():yieldyield2returng=gen()#g是生成器对象print(dis.dis(g))print(**0)print(g.gi_frame.f_lasti)#这里还没有执行,返回的位置是-print(g.gi_frame.f_locals)#这里还没有执行,返回的对象是{}next(g)print(**0)print(g.gi_frame.f_lasti)print(g.gi_frame.f_locals)
返回结果:
0LOAD_CONST()#加载值为2YIELD_VALUE4POP_TOP26LOAD_CONST2(2)8YIELD_VALUE0POP_TOP32LOAD_CONST3()4RETURN_VALUENone**********-#因为还没有执行,所以获取的行数为-{}**********2#这里开始执行了第一次,获取的行数是2,2对应2YIELD_VALUE就是前面加载的数值{}#g.gi_frame.f_locals是局部变量,你都没定义那么获取的结果自然是{},你只需在代码中加上user=admin,这里的{}就会改变。
#-*-coding:utf-8-*-importrandomimportthreadingimportstringimporttimet=time.time()defwrite(x):withopen(a.txt,a+)asa:a.write(x+
)defrun():forxinrange():strs=str(random.randint(,2))+random.choice(string.ascii_letters)*0write(strs)forxinrange(0):t=threading.Thread(target=run)t.start()t2=time.time()print(t2-t)
读取文件代码:
#-*-coding:utf-8-*-defreadbooks(f,newline):#f为传入的文件名,newline为分隔符buf=""#缓存,处理已经读出来的数据量while:whilenewlineinbuf:#缓存中的数据是否存在分隔符pos=buf.index(newline)#如果存在就找到字符的位置,比如0或者或者2yieldbuf[:pos]#暂停函数,返回缓存中的从头到字符的位置buf=buf[pos+len(newline):]#缓存变成了,字符的位置到末尾chunk=f.read(*0)#读取*0的字符ifnotchunk:#已经读取到了文件结尾yieldbufbreakbuf+=chunk#加到缓存withopen(a.txt,r)asf:forlineinreadbooks(f,
):print(line)作者:安全研发来源:安全研发
▍声明:本文整理自网络,如有侵权,请联系删除。
本公号刊载此文,是出于传递更多信息之目的。若有来源标注错误或侵犯了您的合法权益,请随时与我们联系协商,联系(QQ):,我们将及时更正、删除。
喜欢您