Python面向對象編程(四)

一、生成迭代器

       迭代是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面向對象編程系列文章兩週一更!


文章未經博主同意,禁止轉載!

微笑


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章