迭代器与生成器

什么是迭代器协议:
1.迭代器协议是指:对象必须提供一个next方法,执行该方法要么返回迭代中的下一项,
要么就引起一个Stoplteration,已终止迭代
2.可迭代对象:实现迭代器协议的对象(如何实现:对象内部定义一个_iter_()方法)
3.协议是一种约定,可迭代对象实现了迭代器协议,python的内部工具(如for,sum,min,max函数)

x = 'hello'
print(dir(x)) 从这里可以得知,x没有next()方法,但是有_iter_方法,所以严格意义上讲字符串不是可迭代对象
"D:\pycharm new project\venv\Scripts\python.exe" "D:/pycharm new project/01"
['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__',
'__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__',
'__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__',
'__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__',
'__sizeof__', '__str__', '__subclasshook__', 'capitalize', 'casefold', 'center', 'count', 'encode',
'endswith', 'expandtabs', 'find', 'format', 'format_map', 'index', 'isalnum', 'isalpha', 'isdecimal',
'isdigit', 'isidentifier', 'islower', 'isnumeric', 'isprintable', 'isspace', 'istitle', 'isupper',
'join', 'ljust', 'lower', 'lstrip', 'maketrans', 'partition', 'replace', 'rfind', 'rindex', 'rjust',
'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title',
'translate', 'upper', 'zfill']


x = 'hello'
iter_test=x.__iter__()
print(iter_test)
返回一个可迭代对象的内存空间
"D:\pycharm new project\venv\Scripts\python.exe" "D:/pycharm new project/01"
<str_iterator object at 0x00000207CC67DBA8>

x = 'hello'
iter_test=x.__iter__()
print(iter_test.__next__())
print(iter_test.__next__())
print(iter_test.__next__())
print(iter_test.__next__())
print(iter_test.__next__())
依次打印这些东西,但是一旦超过5次数,就会出现报错,StopIteration遇见这个就会停止
"D:\pycharm new project\venv\Scripts\python.exe" "D:/pycharm new project/01"
h
e
l
l
o

for循环工作的原理,就是先i_l=l.__iter_() i_l.__next__()
l=[1,2,3]
for i in l: #i_l=l.__iter_() i_l.__next__()
print(i)

list = [1,2,3]
list1 = list.__iter__() 让list的遵循_iter_(),迭代器协议
print(list1.__next__()) 一旦遵循迭代器协议,就会自动有next()函数
print(list1.__next__())
print(list1.__next__())
print(list1.__next__()) 最后一次的时候报错,遇见StopIteration停止
"D:\pycharm new project\venv\Scripts\python.exe" "D:/pycharm new project/01"
1
2
3
Traceback (most recent call last):
File "D:/pycharm new project/01", line 7, in <module>
print(list1.__next__())
StopIteration

用while方式循环可迭代对象,不用for循环取值,while循环可用这种方式取有序的可迭代对象,但是无序的比如,文件,字典不能用这种方式
list = [1,2,3]
index = 0
while index < len(list):
print(list[index])
index += 1

"D:\pycharm new project\venv\Scripts\python.exe" "D:/pycharm new project/01"
1
2
3

虽然字典是无序的但是也可以遍历 相等于#for i in s:
s={1,2,3}
iter_s=s.__iter__()
print(iter_s)
print(iter_s.__next__())
print(iter_s.__next__())
print(iter_s.__next__())

同样也能遍历文件
f=open('b.txt','r+') 相等于#for i in f:
iter_f=f.__iter__()
print(iter_f.__next__(),end='')
print(iter_f.__next__(),end='')

 

用while模拟for循环,可以得知for循环就是dic.__iter__(),再然后捕捉异常就干了这两件事
dic={'a':1,'b':2,'c':3}
iter_dic=dic.__iter__()
while 1:
try:
k=next(iter_dic)
print(dic[k])
except StopIteration:
break
"D:\pycharm new project\venv\Scripts\python.exe" "D:/pycharm new project/01"
1
2
3

.next()方法,就是相当于iter_l.__next__()
l=['die','erzi','sunzi','chongsunzi']
iter_l=l.__iter__()
print(iter_l)
print(next(iter_l)) #next()---->iter_l.__next__()
print(next(iter_l))
print(next(iter_l))

"D:\pycharm new project\venv\Scripts\python.exe" "D:/pycharm new project/01"
<list_iterator object at 0x0000018FBD3FDD68>
die
erzi
sunzi

 

 

生成器
可以理解为一种数据类型,这种数据类型自动实现了迭代器协议(其他的数据类型需要调用自己的内置_iter_方法)
所以生成器就是可迭代对象

生成器再python的表现形式
1.生成器函数:常规函数定义,使用yield语句而不是return语句返回结果,yield语句一次返回一个结果
再每个结果中间,挂起函数的状态,以便下次重他离开的地方执行
2.生成表达式:类似于列表推导,但是生成器返回按需产生的一个对象,而不是构建一个列表


def test():
yield 1
yield 2
yield 3
g=test()
print('来自函数',g)
print(g.__next__())
print(g.__next__())

"D:\pycharm new project\venv\Scripts\python.exe" "D:/pycharm new project/01"
来自函数 <generator object test at 0x000001D11B390200>
1
2

l=['die','erzi','sunzi','chongsunzi']

iter_l=l.__iter__()
print(iter_l)
print(iter_l.__next__())
print(iter_l.__next__())
print(iter_l.__next__())
print(iter_l.__next__())
print(iter_l.__next__())
print(next(iter_l)) #next()---->iter_l.__next__()

三元表达式
name='alex'
name='linhaifeng'
res='SB' if name == 'alex' else '帅哥'
print(res)

列表解析
egg_list=[]
for i in range(10):
egg_list.append('鸡蛋%s' %i)
print(egg_list)

就相当于再一个列表里面循环加入东西
l=['鸡蛋%s' %i for i in range(10)]
print(l)
"D:\pycharm new project\venv\Scripts\python.exe" "D:/pycharm new project/01"
['鸡蛋0', '鸡蛋1', '鸡蛋2', '鸡蛋3', '鸡蛋4', '鸡蛋5', '鸡蛋6', '鸡蛋7', '鸡蛋8', '鸡蛋9']
['鸡蛋0', '鸡蛋1', '鸡蛋2', '鸡蛋3', '鸡蛋4', '鸡蛋5', '鸡蛋6', '鸡蛋7', '鸡蛋8', '鸡蛋9']

1元 2元 3元
l1=['鸡蛋%s' %i for i in range(10) if i > 5 ]
print(l1)
#l1=['鸡蛋%s' %i for i in range(10) if i > 5 else i] #没有四元表达式
l2=['鸡蛋%s' %i for i in range(10) if i < 5] #没有四元表达式
print(l2)


生成器表达式
laomuji=('鸡蛋%s' %i for i in range(10)) #生成器表达式
print(laomuji)
print(laomuji.__next__())
print(laomuji.__next__())
print(next(laomuji))
print(next(laomuji))
print(next(laomuji))
print(next(laomuji))
print(next(laomuji))
print(next(laomuji))
print(next(laomuji))
print(next(laomuji))
"D:\pycharm new project\venv\Scripts\python.exe" "D:/pycharm new project/01"
<generator object <genexpr> at 0x000001FC7E140200>
鸡蛋0
鸡蛋1
鸡蛋2
鸡蛋3
鸡蛋4
鸡蛋5
鸡蛋6
鸡蛋7
鸡蛋8
鸡蛋9

列表解析就是将[]变成(),都是很好的生成列表的方式,只是生成器表达式节约内存
可以也不加()生成的时候

 

posted @ 2018-05-04 19:19  夏天的麦田  阅读(105)  评论(0)    收藏  举报