一、生成迭代器
迭代是Python最強大的功能之一,是訪問集合元素的一種方式。之前接觸到的Python容器對象都可以用for遍歷。>>>for element in [1,2,3]:
... print(element)
>>>for element in (1,2,3):
... print(element)
>>>for key in {'one':1,'two':2}:
... print(key)
>>>for char in '123':
... print(char)
>>>for line in open('myfile.txt'):
... print(line)
這種編程風格十分簡潔方便。迭代器有兩個基本的方法:iter函數和next函數。for語句在容器對象上調用了iter函數,該函數返回一個定義next函數的迭代對象,它將在容器中逐一訪問元素。當容器遍歷完畢,next函數找不到後續元素時,會引發一個StopIteration異常,告知for循環終止。
>>>L = [1,2,3]
>>>it = iter(L)
>>>it
<list_iterator at 0xa9e0630>
>>>next(it)
1
>>>next(it)
2
>>>next(it)
3
>>>next(it)
Traceback (most recent call last):
File "<ipython-input-9-2cdb14c0d4d6>", line 1, in <module>
next(it)
StopIteration
迭代器(iterator)是一個可以記住遍歷的位置的對象,從第一個元素開始訪問,直到所有的元素被訪問完結束。要注意的是,迭代器只能往前不會後退。
要將迭代器加入到自己的類中,需要定義一個__iter__函數,它返回一個有next方法的對象。如果類定義了next函數,__iter__函數可以只返回self。仍以前面章節(創建類與對象)的Cat類爲例,通過迭代器能輸出對象的全部信息。
>>>class Cat():
... def __init__(self,name,age):
... self.name = name
... self.age = age
... self.info = [self.name,self.age]
... self.index = -1
... def getName(self):
... return self.name
... def getAge(self):
... return self.age
... def __iter__(self):
... print('名字 年齡')
... return self
... def next(self):
... if self.index == len(self.info)-1:
... raise StopIteration
... self.index += 1
... return self.info[self.index]
>>>newcat = Cat('coffe', 3) # 創建對象
>>>print(newcat.getName()) # 訪問對象的屬性
coffe
>>>iterator = iter(newcat.next,1) # 調用迭代函數輸出對象的屬性
>>>for info in iterator:
... print(info)
coffe
3
二、返回迭代器
1. yield
在Python中,使用生成器(generator)可以很方便的支持迭代器協議。生成器是一個返回迭代器的函數,它可以通過常規的def語句來定義,但是不用return返回,而是用yield一次返回一個結果。不像一般的函數會生成值後退出,生成器函數在生成值後會自動掛起並暫停執行狀態並保存狀態信息,這些信息在函數恢復時將再度有效。通過在每個結果之間掛起和繼續它們的狀態來自動實現迭代協議。這裏用一個實例(yield實現斐波那契數列)來區分有yield和沒有yield的情況,對生成器進一步瞭解。
生成器函數——斐波那契數列
>>>import sys
>>>def fibonacci(n,w=0):
... a, b, counter = 0, 1, 0
... while True:
... if (counter > n):
... return
... yield a
... a, b = b, a + b
... print('%d,%d' % (a,b))
... counter += 1
>>>f = fibonacci(10,0) # f是一個迭代器,由生成器返回生成
>>>while True:
... try:
... print (next(f), end=" ")
... except :
... sys.exit()
0 1,1
1 1,2
1 2,3
2 3,5
3 5,8
5 8,13
8 13,21
13 21,34
21 34,55
34 55,89
55 89,144
生成器函數——斐波那契數列
>>>import sys
>>>def fibonacci(n,w=0):
... a, b, counter = 0, 1, 0
... while True:
... if (counter > n):
... return
... # yield a # 不執行yield語句
... a, b = b, a + b
... print('%d,%d' % (a,b))
... counter += 1
>>>f = fibonacci(10,0) # f是一個迭代器,由生成器返回生成
>>>while True:
... try:
... print (next(f), end=" ")
... except :
... sys.exit()
1,1
1,2
2,3
3,5
5,8
8,13
13,21
21,34
34,55
55,89
89,144
在調用生成器運行的過程中,每次遇到yield時函數會暫停並保存當前所有的運行信息,返回yield的值。並在下一次執行next函數時從當前位置繼續運行。
簡而言之,包含yield語句的函數會被特地編譯成生成器。當函數被調用時,他們返回一個生成器對象,這個對象支持迭代器接口。
2. 生成器表達式
列表解析一般的形式如下。expr for iter_var in iterable if cond_expr
迭代iterable裏所有內容,每一次迭代後,把iterable裏滿足cond_expr條件的內容放到iter_var中,再在表達式expr中應用iter_var的內容,最後用表達式的計算值生成一個列表。
例如,生成一個list來保護50以內的所有奇數。
[i for i in range(50) if i%2]
當序列過長,而每次只需要獲取一個元素時,應當考慮使用生成器表達式而不是列表解析。生成器表達式的語法和列表解析一樣,只不過生成器表達式是被圓括號()括起來的,而不是方括號[ ]。
(expr for iter_var in iterable if cond_expr)
三、練習
在流程控制語句中已經接觸過迭代方式,而現在是面向對象過程中對象的迭代。現在將對Car類進行迭代,增加品牌(brand)和廢氣渦輪增壓(T)兩個屬性,並依次輸出所有屬性。參考代碼:
class Car():
def __init__(self,brand, newWheelNum, newColor,T):
self.brand = brand
self.wheelNum = newWheelNum
self.color = newColor
self.T = T # T爲廢氣渦輪增壓
self.info = [self.brand,self.wheelNum,self.color,self.T]
self.index = -1
def getBrand(self):
return self.brand
def getNewheelnum(self):
return self.wheelNum
def getNewcolor(self):
return self.color
def getT(self):
return self.T
def __iter__(self):
print('品牌 車輪數 顏色 廢氣渦輪增壓')
return self
def next(self):
if self.index == 3:
raise StopIteration
self.index += 1
return self.info[self.index]
newcar = Car('BMW',4, 'green',2.4) # 創建對象
print(newcar.getNewcolor()) # 訪問屬性
iterator = iter(newcar.next,1) # 調用迭代函數輸出對象的屬性
for info in iterator:
print(info)
Python面向對象編程系列文章兩週一更!
文章未經博主同意,禁止轉載!