python_學習筆記0825

今天是二零一伍年八月二十五日

1、在python中有像list、tuple這樣的對象,他們是可迭代的(Iterable),這樣的對象在for語句中被循環。但是我們都知道,list是一個有限的對象。也就是說,其實當list被創建以後,他是具有長度的,每一個元素在內存中都是有位置的。但是有時候,在一個list裏面,我們有時候只需要前面幾個元素,這樣就造成了大量內存浪費。爲了防止這種浪費,我們就需要一種新的數據類型——生成器(generator)

顧名思義,生成器是動態生成內容的,比如:

l = [x * x for x in range(10)]
g = (x *x for x in range(10) )

把原來的方括號修改爲圓括號,就是我們的生成器了。g的列舉更加靈活:
>>> next(g)
0
>>> next(g)
1
>>> next(g)
4
>>> next(g)
9
>>> next(g)
16
>>> next(g)
25
>>> next(g)
36
>>> next(g)
49
>>> next(g)
64
>>> next(g)
81
>>> next(g)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

next()語句幫助我們一步一步的“計算”生成器中的值。生成器中保留的其實是一種算法和計數器,每次使用next時,就計算下一個元素的值。當然,在我們的算法裏也有一個上限,所以我們在訪問到最後就會有StopIteration的異常被拋出。當然我們的生成器也可以像其他可迭代對象一樣被for循環直接輸出。

但是有時候,生成一個有邏輯的序列卻並不是那麼簡單。比如斐波那契數列,我們們能僅僅用列表生成器就生成嗎?不行,這個時候必須使用函數:

# generator.py
def fib(max):
	n , a , b = 0 , 0 , 1
	while n < max :
	 	print(b)
	 	a , b = b , a + b 
	 	n += 1 
	 return 'done'


那麼我們能用生成器生成一個動態斐波拉切嗎,答案是可以的。那麼我們就來分析一下斐波拉切函數,在這個函數裏,我們真正需要的其實是b這個變量,而print這個函數正好是輸出了這個變量。所以,想要把這個函數變成生成器,我們要從這裏入手,我們只用把打印語句改成yield b就行,也就是這樣:
# generator.py
def fib(max):
	n , a , b = 0 , 0 , 1
	while n < max :
	 	yield b
	 	a , b = b , a + b 
	 	n += 1 
	 return 'done'


這個時候我們再嘗試去使用這個函數的時候就不一樣了。

g = fib(6)

此時的g就是一個生成器了,我們使用next或者是for循環就能打印出我們的斐波拉切數列。但是我們看回我們的定義,發現我們還有一個done被return了,那麼它到底什麼時候被返回呢?這個我想大家不用想也知道,它會在我們原先被拋出異常的時候返回,也就是:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration: done

當然要是我們想正常輸出這個done的話,我們就需要捕獲異常了


2、剛剛在使用生成器的時候使用了Next句柄,那麼,是否還有其他的對象也可以使用next?答案是當然的,這樣的對象我們統一稱爲——迭代器(Iterator)。那麼我們的list、string是迭代器嗎?答案是否定的,關於這一點我們可以使用isinstance函數去檢驗。他們只是可迭代的(Iterable),遠不是迭代器。不過沒有關係我們可以使用iter()函數使它變成迭代器。

>>> from collections import Iterator
>>> isinstance((x for x in range(10)), Iterator)
True
>>> isinstance([], Iterator)
False
>>> isinstance({}, Iterator)
False
>>> isinstance('abc', Iterator)
False


>>> isinstance(iter([]), Iterator)
True
>>> isinstance(iter('abc'), Iterator)
True

那麼爲什麼我們所鍾愛的這些數據類型不能成爲迭代器呢?因爲我們所稱的迭代器往往是一個數據流,它往往需要next函數去一個一個計算下一個值。有時候我們稱迭代器是惰性的,只有當我們需要下一個數據的時候他纔會計算。









發佈了35 篇原創文章 · 獲贊 2 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章