一.什么是迭代器
迭代指的是一个重复的过程,每一次重复都是基于上一次的结果而来的
迭代器指的是迭代取值的工具,该工具的特点是可以不依赖于索引取值
二.为何要用迭代器
为了找出一种通用的和可以不依赖于索引的迭代取值方式
三.如何使用迭代器
1. 可迭代的对象:但凡内置有.__iter__方法的对象都称之为可迭代的对象
2. 迭代器对象:既内置有__iter__方法,又内置有__next__方法
3.关于__iter__方法:
调用可迭代对象的__iter__会得到一个迭代器对象
调用迭代器对象的__iter__会得到迭代器本身
4.可迭代的对象:str,list,tuple,dict,set,文件对象
迭代器对象:文件对象
可迭代的对象-------->迭代器对象:调用可迭代对象内置的__iter__方法会有一个返回值,该返回值就是对应的迭代器对象
四.for循环原理分析及迭代器总结
for准确地说应该是迭代器循环,for循环的原理如下:
1.先调用in后面那个值的__iter__方法,得到迭代器对象
2.执行迭代器.__next__方法得到一个返回值,然后赋值给一个变量k,运行循环体代码
3.循环往复,直到迭代器取值完毕抛出异常然后捕捉异常自动结束循环
dic={"x":1,"y":2,"z":3}
iter_dic=dic.__iter__()
print(iter_dic) #<dict_keyiterator object at 0x0000000001F7CA98>
print(iter_dic.__iter__()) #<dict_keyiterator object at 0x0000000001F7CA98>
for k in dic: #iter_dic=dic.__iter__()
print(k)
迭代器的优缺点:
优点:
1.提供了一种通用的&可以不依赖于索引的迭代取值方式
2.同一时刻在内存中只有一个值,更加节省内存(是在基于本身造出来的数据对象是迭代器对象或者是自定义迭代器的基础上的)
缺点:
1.取指定值不如索引灵活,并且迭代器是一次性的
2.无法预知迭代器数据的个数
五.生成器
只要函数内部包含有yield关键字,那么函数名()得到的结果就是生成器,(生成器的本质就是迭代器),并且不会执行函数内部的代码
def func():
print("-------->1")
yield 1
print("-------->2")
yield 2
print("-------->3")
yield 3
print("-------->4")
yield 4
g=func()
print(g) #<generator object func at 0x000000000216B318>
res1=next(g) #g.__next__()
res2=next(g)
res3=next(g)
res4=next(g)
print(res1)
print(res2)
print(res3)
print(res4)
"""
<generator object func at 0x000000000218B318>
-------->1
-------->2
-------->3
-------->4
1
2
3
4
"""
总结yield:
1.提供一种自定义迭代器的解决方案
2.yield可用于返回值
yield VS return
相同点:都可以用于返回值
不同点:yield可以暂停函数,yield可以返回多次值,而return只能返回一次值函数就立刻终止
六.自定义迭代器
def myiter(start,stop,step=1):
while start<stop:
yield start
start+=step
g=myiter(1,10,2)
res1=next(g)
res2=next(g)
res3=next(g)
print(res1)
print(res2)
print(res3)
"""
1
3
5
"""
from collections.abc import Iterable,Iterator
class Company(object):
def __init__(self,employee_list):
self.employee=employee_list
def __iter__(self):
return Myiterator(self.employee)
# def __getitem__(self, item):
# return self.employee[item]
class Myiterator(Iterator):
def __init__(self,employee_list):
self.iter_list=employee_list
self.index=0
def __next__(self):
#真正返回迭代逻辑值
try:
word=self.iter_list[self.index]
except IndexError:
raise StopIteration
self.index+=1
return word
if __name__ == '__main__':
company=Company(["tom","bob","jane","petrus"])
# print(isinstance(company,Iterable))
my_itor=iter(company)
# while True:
# try:
# print(next(my_itor))
# except StopIteration as e:
# pass
for item in company:
print(item)
"""
for 语句的内部实现原理就是上面的while 循环 for语句内部帮我们处理了StopIteration异常
"""
.三元表达式
res="条件成立的值" if x>y else "条件不成立的值"
七.xx生成式
#列表生成式
l=["egg %s" %i for i in range(1,11) if i>4]
print(l)
#列表生成式
names=["egon","alex","yxx","cw"]
l2=["%s_DSB" %name for name in names if name!="egon" ]
print(l2)
#生成器表达式
res=(i**2 for i in range(3))
print(res)
print(next(res))
print(next(res))
print(next(res))
"""
<generator object <genexpr> at 0x000000000214B318>
0
1
4
"""
#字典生成式
items=[("name","egon"),("age",18),("sex","male")]
dic={}
for k,v in items:
dic[k]=v
print(dic)
res={k:v for k,v in items if k!="sex"}
print(res)
生成器读取大文件例子:
假设有一个文件input.txt,如下所示:
Why?{|} Because this tutorial uses a specific set of data to ensure consistency in your search results and the features that you are learning about. In the tutorial,{|} you will upload this tutorial-specific data to the Splunk platform.{|} You might not have permission to upload data in your production,{|} work environment. Additionally,{|} using a free Trial version of the software ensures that the tutorial data is not mixed in with your work data.
demo:
def myreadlines(f,newline):
buf="" #缓存,处理已经读出的数据量
while True:
while newline in buf: #刚开始buf为0 while不成立 这个while循环处理的是可能一次性把两行数据读入一个buf里面
pos=buf.index(newline) #3
yield buf[:pos]
buf=buf[pos+len(newline):]
print(len(newline))
print(buf)
chunk=f.read(4096) #会读取4096*10个字符
if not chunk:
#说明已经读到了文件结尾
yield buf
break
buf+=chunk
with open("input.txt",'r') as f:
for line in myreadlines(f,"{|}"):
print(line)