python-迭代器生成器
python-迭代器生成器
目錄python 三大利器, 迭代器,生成器和裝飾器
迭代是Python中常用且非常強大的一個功能,可以被for迴圈的就是可迭代的,目前有字串,列表,元組,字典,集合。 通過使用兩個單獨方法來實現的;它們被用於允許使用者自定義類對迭代的支援。
可迭代物件iterable
是Python中一個非常龐大的概念,它主要包括如下三類
-
迭代器 (生成器)
-
序列(字串、列表、元組)
-
字典
-
可迭代物件需要實現
__iter__
方法 -
迭代器不僅要實現
__iter__
方法,還需要實現__next__
方法 -
生成器是一個返回迭代器的函式,使用了yield,
迭代器是可迭代物件的一個子集,而生成器又是迭代器的一個子集,是一種特殊的迭代器。除了迭代器之外,Python中還有序列、字典等可迭代物件。
可迭代物件
可迭代協議: 能被for迴圈的就是“可迭代的”, 可迭代協議的定義:內部實現了__iter__
方法。
iterator.__iter__()
alist=[1,2]
print(alist.__iter__())
#<list_iterator object at 0x1024784a8>
返回迭代器物件本身。 如 range(),str,list,tuple,dict,set
迭代器(iterator)
l = [1,2,3]
l_iter = l.__iter__()
item = l_iter.__next__()
print(item)
item = l_iter.__next__()
print(item)
item = l_iter.__next__()
print(item)
item = l_iter.__next__()
print(item)
#
1
2
3
StopIteration
迭代器遵循迭代器協議:必須擁有__iter__
方法和__next__
方法。
如 iter(range()),iter(str),iter(list),iter(tuple),iter(dict),iter(set)
迭代器是可迭代物件的一個子集,它是一個可以記住遍歷的位置的物件,它與列表、元組、集合、字串這些可迭代物件的區別就在於next方法的實現,其他列表、元組、集合、字串這些可迭代物件可以很簡單的轉化成迭代器,通過Python內建的iter函式能夠輕鬆把可迭代物件轉化為迭代器
構造迭代器iter(),next()
# 內建函式**iter()** 函式用來生成迭代器
iter(object[, sentinel])
'''輸入引數
object -- 支援迭代的集合物件, 可迭代物件
sentinel -- 如果傳遞了第二個引數,則引數 object 必須是一個可呼叫的物件
'''
x_list = [1,2,3,4,5]
y_list=iter(x_List)
print(type(x_List)) # <class 'list'>
print(type(y_list)) # <class 'list_iterator'>
print(y_list)
print(next(y_list)) # <list_iterator object at 0x0000016A17F231F0>
print(next(y_list)) # 1
print(next(y_list)) # 2
# 通過iter函式把list轉化成了迭代器
# 迭代器能夠記住遍歷位置,能夠通過next方法不斷從前往後訪問
# 自定義類
class MyNumbers:
def __iter__(self):
self.a = 1
return self
def __next__(self):
if self.a <= 20:
x = self.a
self.a += 1
return x
else:
raise StopIteration # StopIteration 異常用於標識迭代的完成
myclass = MyNumbers()
myiter = iter(myclass)
print(next(myiter))
print(next(myiter))
print(next(myiter))
print(next(myiter))
print(next(myiter))
迭代器有兩種:一種是呼叫方法直接返回的,一種是可迭代物件通過執行iter方法得到的,迭代器有的好處是可以節省記憶體。
生成器
生成器是迭代器的子集,換句話說,生成器一定是迭代器,但是迭代器不全是生成器物件。
- 生成器函式:常規函式定義,但是,使用yield語句而不是return語句返回結果。yield語句一次返回一個結果,在每個結果中間,掛起函式的狀態,以便下次重它離開的地方繼續執行
- 生成器表示式:類似於列表推導,但是,生成器返回按需產生結果的一個物件
- 本質:迭代器(所以自帶了
__iter__
方法和__next__
方法,不需要我們去實現) - 特點:惰性運算,開發者自定義
在Python中,這種一邊迴圈一邊計算的機制,稱為生成器:generator,生成器是一個返回迭代器的函式, 生成器是一個特殊的程式,可以被用作控制迴圈的迭代行為,使用yield返回值函式,每次呼叫yield會暫停,而可以使用next()函式和send()函式恢復生成器。
Python中的關鍵字yiled,在Python中一個函式可以用yiled替代return返回值,這樣的話這個函式就變成了一個生成器物件
def generator(array):
for i in array:
return i
gen = generator([1,2,3,4,5])
print(type(gen))
# 輸出
<class 'int'>
def fun_generator(array):
for i in array:
yield(i)
gen = fun_generator([1,2,3,4,5])
print(type(gen))
# 輸出 呼叫一個生成器函式,返回的是一個迭代器物件。
<class 'generator'>
# 例項使用 yield 實現斐波那契數列
def fibonacci(n): # 生成器函式 - 斐波那契
a, b, counter = 0, 1, 0
while True:
if (counter > n):
return
yield a
a, b = b, a + b
counter += 1
f = fibonacci(10) # f 是一個迭代器,由生成器返回生成
while True:
try:
print (next(f), end=" ")
except StopIteration:
sys.exit()
列表推導式和生成器表示式
X = [1, 2, 3, 4, 5]
it = [i for i in X]
gen = (i for i in X)
print(type(X))
print(type(it))
print(type(gen))
# 輸出
<class 'list'>
<class 'list'>
<class 'generator'>
# 使用中括號的叫做列表生成式, 惰性計算,延遲求值
# 獲得的返回值是一個列表,而使用小括號叫做生成器表示式,獲得的返回結果是一個生成器
gen = (i for i in X)
for i in gen:
print(i)
# 輸出
1
2
3
4
5
應用特點
對於大資料量處理,將會非常有用。
#列表解析
sum([i for i in range(100000000)]) #記憶體佔用大,機器容易卡死
#生成器表示式
sum(i for i in range(100000000)) #幾乎不佔記憶體
迭代器在編碼方面更加簡潔,這是顯而易見的,其次生成器執行速度更快,最後一點,也是需要著重說明的一點:節省記憶體.
4G 記憶體處理 10G 大小的檔案
# 方法1
# 僅使用 Python 內建模板,逐行讀取到記憶體。
# 使用 yield,好處是解耦讀取操作和處理操作:
def python_read(filename):
with open(filename,'r',encoding='utf-8') as f:
while True:
line = f.readline()
if not line:
return
yield line
if __name__ == '__main__':
g = python_read('./data/movies.dat')
for c in g:
print(c)
# process c
方法一有缺點,逐行讀入,頻繁的 IO 操作拖累處理效率。
# 方法2
# 使用pandas 包 read_csv 函式,引數有 38 個之多,功能非常強大
def pandas_read(filename,sep=',',chunksize=5):
reader = pd.read_csv(filename,sep,chunksize=chunksize)
while True:
try:
yield reader.get_chunk()
except StopIteration:
print('---Done---')
break
使用如同方法一:
if __name__ == '__main__':
g = pandas_read('./data/movies.dat',sep="::")
for c in g:
print(c)
# process c