1. 程式人生 > 實用技巧 >迭代器和生成器

迭代器和生成器

一、迭代器

1、什麼是迭代?
迭代是一個重複的過程,並且每次重複都是基於上一次的結果而來
2、要想了解迭代器到底是什麼?必須先了解一個概念,即什麼是可迭代的物件?
可迭代的物件:在python中,但凡內建有__iter__方法的物件,都是可迭代的物件

字串,列表,元組,集合,字典都是可迭代的
#以下都是可迭代的物件
# str1='hello'
# list1=[1,2,3]
# tup1=(1,2,3)
# dic={'x':1}
# s1={'a','b','c'}
# f=open('a.txt','w',encoding='utf-8')
3、迭代器:迭代取值工具,可迭代的物件執行__iter__
方法得到的返回值就是迭代器物件
dic={'x':1,'y':2,'z':3}
iter_dic=dic.__iter__()
print(iter_dic)
print(iter_dic.__next__())
print(iter_dic.__next__())
print(iter_dic.__next__())
# print(iter_dic.__next__())  #報錯  StopIteration

'''
<dict_keyiterator object at 0x02E5FC60>
x
y
z
'''

s1={'a','b','c'}
iter_s1=s1.__iter__
() print(iter_s1.__next__()) print(iter_s1.__next__()) print(iter_s1.__next__()) print(iter_s1.__next__()) #報錯 StopIteration ''' b c a '''
4、可迭代的物件vs迭代器物件?
可迭代的物件:str,list,tuple,dict,set,file
1、獲取可迭代物件的方式:無須獲取,python內建str,list,tuple,dict,set,file都是可迭代物件
2、特點:
    內建有__iter__方法的都叫可迭代的物件,執行該方法會拿到一個迭代器物件

 迭代器物件:檔案物件本身就是迭代器物件
1、獲取迭代器物件的方式: 執行可迭代物件的__iter__方法,拿到的返回值就是迭代器物件 2、特點: 內建有__next__方法,執行該方法會拿到迭代器物件中的一個值 內建有__iter__方法,執行該方法會拿到迭代器本身

5、迭代器優缺點分析

#5.1 迭代器的優點:
#5.1.1、提供了一種可不依賴於索引的取值方式
l=open('a.txt','r',encoding='utf-8')
iter_l=l.__iter__()
while True:
    try:
        print(iter_l.__next__(),end='')
    except StopIteration:
        break#5.1.2 迭代器更加節省記憶體
item=range(0,10000000000000000000)
print(item)


#5.2迭代器的缺點:
#5.2.1、取值麻煩,只能一個一個取,只能往後取,
#5.2.2、並且是一次性的,無法用len獲取長度

x=[1,2,3]
iter_x=x.__iter__()
while True:
    try:
        print(iter_x.__next__())
    except StopIteration:
        break

6、for迴圈原理分析

(1) for 迴圈稱之為迭代器迴圈,in後跟的必須是可迭代的物件
(2) for迴圈會執行in後物件的__iter__方法,拿到迭代器物件
(3) 然後呼叫迭代器物件的__next__方法,拿到一個返回值賦值給line,執行一次迴圈體
(4) 周而復始,直到取值完畢,for迴圈會檢測到異常自動結束迴圈
# l=open('a.txt','r',encoding='utf-8')
# for line in l: #iter_l=l.__iter__()
#     print(line)

for item in {'x':1,'y':2}:
    print(item)

二、生成器

(1) 函式內包含有yield關鍵字,
(2) 再呼叫函式,就不會執行函式體程式碼,拿到的返回值就是一個生成器物件
(3) 生成器的本質就是迭代器,其用法和迭代器類似

示例:

def chicken():
    print('=====>first')
    yield 1
    print('=====>sencond')
    yield 2
    print('=====>third')
    yield 3


obj=chicken()
print(obj)  #<generator object chicken at 0x03032830>

#1、iter_obj=obj.__iter__(),拿到迭代器
#2、iter_obj.__next__(),拿到該方法的返回值,賦值給item
#3、周而復始,直到函式內不在有yield,即取值完畢
#4、for會檢測到StopIteration異常,結束迴圈

小節:

1、為我們提供了一種自定義迭代器的方式,
可以在函式內用yield關鍵字,呼叫函式拿到的結果就是一個生成器,生成器就是迭代器
2、yield可以像return一樣用於返回值,區別是return只能返回一次值,而yield可返回多次
因為yield可以儲存函式執行的狀態

小示例:

def eat(name):
    print('%s ready to eat' %name)
    food_list=[]
    while True:
        food=yield food_list # food='骨頭'
        food_list.append(food) #food_list=['泔水','骨頭']
        print('%s start to eat %s' %(name,food))


dog1=eat('bw')

#1、必須初始化一次,讓函式停在yield的位置
res0=dog1.__next__()
print(res0)

#2、接下來的事,就是喂狗
#send有兩方面的功能
#1、給yield傳值
#2、同__next__的功能
res1=dog1.send('蘋果')
print(res1)
res2=dog1.send('橘子')
print(res2)
res3=dog1.send('西瓜')
print(res3)

'''
bw ready to eat
[]
bw start to eat 蘋果
['蘋果']
bw start to eat 橘子
['蘋果', '橘子']
bw start to eat 西瓜
['蘋果', '橘子', '西瓜']
'''