1. 生成式
通過列表生成式,我們可以直接創建一個列表。格式是:[exp for val in collection if condition]
相當於
result=[]
for val in collection:
if(condition):
result.append(exp)
例子:
list1 = [x*x for x in xrange(1,11) if x %2 == 0]
print (type(list1))
print (list1)
結果:
<type 'list'>
[4, 16, 36, 64, 100]
##通過生成式創建的列表,受到內存限制,列表容量肯定是有限的。而且,創建一個包含100萬個元素的列表,不僅佔用很大的存儲空間,如果我們僅僅需要訪問前面幾個元素,那後面絕大多數元素佔用的空間都白白浪費了。
如果列表元素可以按照某種算法推算出來,那我們是否可以在循環的過程中不斷推算出後續的元素呢?這樣就不必創建完整的list,從而節省大量的空間。在Python中,這種一邊循環一邊計算的機制,稱爲生成器(Generator)。
a.創建一個生成器
第一種方法是把一個列表生成式的[]改成(),就創建了一個generator:
list1 = (x*x for x in xrange(1,11) if x %2 == 0)
print (type(list1))
print (list1.next())
print (list1.next())
print (list1.next())
print (list1.next())
print (list1.next())
結果:
<type 'generator'>
4
16
36
64
100
解釋:generator保存的是算法,每次調用next(),就計算出下一個元素的值,直到計算到最後一個元素爲止.
b.第二種方法,如果一個函數定義中包含yield關鍵字,那麼這個函數就不再是一個普通函數,而是一個generator:
yield的使用例子
def fun(n):
sum = 0
i = 0
while i < n:
sum += i
i += 1
print (sum)
fun(10)
結果爲:
0
1
3
6
10
15
21
28
36
45
這個程序就是求0到9所有數字之和,接下來,我們只要稍微改動一下,你看看有什麼差別,
def fun(n):
sum = 0
i = 0
while i < n:
sum += i
i += 1
yield(sum)
for x in fun(10):
print(x)
print(type(fun(10)))
結果爲:
0
1
3
6
10
15
21
28
36
45
<type 'generator'>
結果和上面的結果是一樣的,包含yield語句的函數會被特地編譯成生成器。當函數被調用時,他們返回一個生成器對象,這個對象支持迭代器接口。每當遇到yield關鍵字的時候,你可以理解成函數的return語句,yield後面的值,就是返回的值。但是不像一般的函數在return後退出,生成器函數在生成值後會自動掛起並暫停他們的執行和狀態,他的本地變量將保存狀態信息,這些信息在函數恢復時將再度有效,下次從yield下面的部分開始執行。
解釋:
1.以上函數有關鍵字yield,所以生成的是一個生成器。
2.通過for循環調用生成器,當執行到yield的時候,返回sum的值,sum爲0,此時暫停並記錄sum的值
3.打印sum的值,然後繼續往下執行。此時跳入下一個循環while(1<10)
4.直到遇到yield的時候,返回sum的值。
5.反覆執行3,4步驟,知道循環結束,最終程序退出生成式與生成器的區別:
一個直接返回了表達式的結果列表, 而另一個是一個對象,該對象包含了對錶達式結果的計算引用, 通過循環可以直接輸出
生成器不會一次性列出所有的數據,當你用到的時候,在列出來,更加節約內存的使用率。
3.迭代器
Iterable(可迭代對象和Iterator(迭代器)主要區別是 :
凡是可以用 for 循環的 都是 Iterable(可迭代對象)凡是需要通過next()函數獲得值的可迭代對象都是 Iterator(迭代器)。
(所以生成器可以 被next()函數調用並不斷返回下一個值的對象稱爲迭代器 ) (可以簡單理解爲生成器 就是 迭代器的可迭代對象)
凡是可作用於for循環的對象都是Iterable類型;
凡是可作用於next()函數的對象都是Iterator類型,它們表示一個惰性計算的序列;
a = [1,2,3,4,5]
print type(a)
b = iter(a)
print type(b)
結果爲
<type 'list'>
<type 'listiterator'>