标签:取数据 传参 打印 send ima next 读取列表 bsp font
可迭代协议:
含有双下方法__iter__的对象就是可迭代对象。
迭代器协议:
同时含有__iter__和__next__方法的对象就是迭代器。
print(dir([])) #列表内置的方法 print(dir([].__iter__())) #__iter__中内置的方法 print(set(dir([].__iter__())) - set(dir([])))#将得到的方法列表转换成集合,相减得到__iter__方法中独有的内置方法 print(dir([]).__iter__()) #一个可迭代对象加上__iter__方法就是迭代器 print(({}).__iter__()) #字典也是如此
打印截图:
例:
i = [1,2,3,4,5,6,7,8,9,10,11,12,13] ix = i.__iter__() print(ix.__length_hint__()) #打印这个可迭代对象中的元素个数 print(ix.__setstate__(3)) #指定开始打印位置,参数为下标,返回值为None print(ix.__next__())#一条一条打印,这里为4 print(ix.__next__())#5 print(ix.__next__())#6 for s in ix: #内存已经读取列表所有元素,但是从7开始,证明读取一个元素之后,该元素会从内存中释放,也就是说,迭代器读取数据的方式是一条一条的读(读完一个释放一个) print(s)#7,8,9,10,11,12,13
# print(ix.__next__())#报错 数据已经读取完毕,内存被释放,读不到数据 #打印: 13 None 4 5 6 7 8 9 10 11 12 13
结论:
1、__iter__方法中独有三个内置方法,__length_hint__,__next__,__setstate__。分别的作用是,查看元素的个数,一条一条打印,从哪个位置打印
2、含有__iter__方法的对象就是可迭代对象(可迭代协议)
3、同时含有__iter__方法和__next__方法,那么它就是迭代器(迭代器协议)
4、__iter__方法中包含__next__方法,但不是在同一个层级当中,所以只有__iter__方法不是迭代器,仅仅是一个可迭代对象
5、当一个可迭代对象引用了__iter__方法时,那么这个对象就是迭代器
6、迭代器读取数据的方式可以是用__next__一条一条的读,读取一个元素之后,该元素会从内存中释放,也就是说,迭代器读取数据的方式是一条一条的读(读完一个释放一个),当数据读完还要读取时会报错
迭代器的好处:
从容器类型中一个一个的取值,会把所有的值都取到。
节省内存空间,迭代器并不会在内存中再占用一大块内存,而是随着循环每次生成一个;每次next每次给我一个
生成器函数和生成器:
def generator(): print(‘a‘) yield ‘1‘ print(‘b‘) yield ‘2‘ print(‘c‘) yield ‘3‘ print(‘d‘) yield ‘4‘ print(generator().__next__())#函数调用后返回一个生成器,直接执行生成器:1 print(generator().__next__())#每次调用函数都会返回一个新的生成器:1 print(generator().__next__())#每次调用函数都会返回一个新的生成器:1 g = generator() #函数调用后返回一个生成器,把它赋值给g,生成一个新的生成器g print(g) 新的生成器的地址 print(g.__next__())#获取生成器g的数据:1 print(g.__next__()):#2 print(g.__next__()):#3 #打印: a 1 a 1 a 1 <generator object generator at 0x000001D03DBCDB48> a 1 b 2 c 3
结论:
含有yield关键字的函数都是生成器函数,且不能和return一起使用,且需要写在函数体内。yield也可以设置返回值,执行yield后并不会结束程序
生成器是一个迭代器,生成器函数调用后会返回一个生成器,此时并不会执行函数体内的程序。当把这个生成器重新赋值给一个对象时,会形成一个新的生成器,
执行生成器时,才会执行函数体内的程序。每次调用生成器函数都是返回一个新的生成器,所以不创建对象进行接收生成器时,直接打印是无法获取全部的数据。
send方法:
def generator(): print(‘a‘) b = yield 1 print(‘b‘,b) yield 2 print(‘c‘) yield 3 print(‘d‘) l = yield 4 print(l) g = generator() # print(g.send(111))#报错,因为此时没有对应的yield能够接收参数 # print(g.send(None))#不报错,传参值设置为空时,程序直接向下执行 print(g.__next__())#此时程序停在yield 1 # print(g.send(None)) # print(g.send()) #报错 print(g.send(‘这是一条被send传过来的参数‘))#执行到这里时,传入的字符串被yield 1接收,赋值给b,程序继续向下执行,打印字符串b,调用b,继续向下执行,返回yield的数据2 print(g.__next__()) print(g.__next__()) #print(g.send(111))#报错,传入的参数被yield 4接收,但下方已经没有数据可供读取 #打印: a 1 b 这是一条被send传过来的参数 2 c 3 d 4
结论:
send与next的作用一样,会返回一条数据,且send支持传参:
send不传参会报错,传的参数被上一个yield接收,然后程序继续向下执行,继续返回一条数据。
获取生成器第一条数据不能使用send进行传参,因为没有对应的yield可以接收参数,传参值设置为None时,程序直接向下执行,不报错。
获取生成器最后一条数据之后使用send进行传参同样会报错,传入的参数被yield接收,但数据已经读取完毕,没有多余的数据能够读取,但传入的参数有效。
标签:取数据 传参 打印 send ima next 读取列表 bsp font
原文地址:https://www.cnblogs.com/aizhinong/p/11374011.html