迭代器,生成器,可迭代物件
阿新 • • 發佈:2021-10-14
迭代器,生成器
迭代器
一個類,如果實現:
- 實現
__iter__(self)
方法,並返回自身self
- 實現
__next__(self)
方法,返回迭代的值。
舉例:
from collections.abc import Iterator,Iterable class it(object): def __init__(self, num): self.num = num def __iter__(self): return self def __next__(self): self.num += 1 # 大於10,丟擲異常 if self.num > 10: raise StopIteration return self.num ge = it(1) print(isinstance(ge,Iterable)) print(isinstance(ge,Iterator))
可迭代物件
實現了 __iter__(self)
, 返回一個迭代器,就是一個可迭代物件。
iter()
可以將一個可迭代物件轉變成一個迭代器。
from collections.abc import Iterator,Iterable
class it(object):
def __iter__(self):
return iter([1,2,3])
ge = it(1)
print(isinstance(ge,Iterable))
print(isinstance(ge,Iterator))
生成器
使用 yield
關鍵字,可以實現生成器, 而且可以直接使用 next()
class generator(object):
def __init__(self, num):
self.num = num
def __iter__(self):
while self.num < 10:
yield self.num
self.num += 1
ge = generator(1)
print(type(ge))
print(isinstance(ge,Iterable))
print(isinstance(ge,Iterator))
當然,上面是一個生成器類,其實生成器跟 __iter__()
yield
關鍵字就行了:
def generator():
yield 1
g = generator()
print(g)
生成器的 next(), send(), yield from
next(generator)
很簡單,就是不停的執行從當前程式碼,執行到下一個 yield
處,返回當前 yield 的資料
send(msg)
可以給生成器傳送資料,進行資料互動,然後執行到下一個 yield
處,返回 yield 的資料。如果沒有可以用來接收資料的變數,則和 next(generator)
效果一樣。生成器沒有啟動時,第一次使用 send()
,必須先發送一個 send(None)
,因為此時還沒有 yield 表示式可以來接收值。
yield from <generator>
它可以讓兩個生成器互動。可以從當前生成器,進入到另一個生成器執行,執行完畢後,再回到當前生成器。
def inner():
print('enter inner')
value = yield 2 # 第二次截止到: yield 2 ; # 第三次從賦值開始: value = send傳遞過來的值
print('inner value:',value)
yield 3 # 第三次完畢
return 'inner_return' # 第四次開始
def outer():
print('outer entered')
yield 1 # 第一次截至到這裡
value = yield from inner() # 第二次起始:進入另一個生成器
yield 4 # 第四次結束
print('back to outer') # 第五次開始
print('value is :', value) # 第五次結束,並丟擲 StopIteration 異常
o = outer()
print(next(o)) # 沒啥好說的,往下走
print(next(o)) # 沒啥好說的,往下走到 yield 2
print(next(o)) # 沒法傳送資料,所以 yield 2 前面的 value 會是 None
print(next(o)) # 沒啥好說的,不停的往下走
print(next(o)) # 沒啥好說的,不停的往下走
# ==================================================
o = outer()
print(o.send(None)) # o.send(None) 等同於 next(o),第一次必須傳送 None,先走到 yield 程式碼處
print(o.send('HH')) # 儘管發了一個數據:HH,但是第1次 yield 1 前面沒有接收這個資料的變數,所以直接走向下一個 yield
print(o.send('HHH')) # 上一次 yield 停止的地方:value = yield 2 有個變數可以接收值,所以給 value 賦值,然後走到下一個 yield 處
print(o.send('HHHH'))
print(o.send('HHHHH'))
for 迴圈
for 迴圈,可以迴圈迭代器,生成器,可迭代物件。它的原理,就是先執行要迴圈的物件的__iter__()
方法,獲得一個迭代器,然後執行迭代器的 __next__()
方法,並且在迴圈完畢時,處理一下 StopIteration
異常。雖然我們寫函式式的生成器時沒有__iter__()
方法,但是它已經內建了這個方法。
譬如:
def it():
yield 1
ge = it()
print(dir(ge))
i = ge.__iter__()
print(dir(i))
print(next(i))
class it(object):
def __iter__(self):
return iter([1,2,3])
# ------- for --------
for i in it():
print(i)
# ------- 原理 --------
i = it().__iter__()
while True:
try:
print(next(i))
except StopIteration:
break