「Python網絡編程」迭代器和生成器(四)

博主前言:

「2020本來是充滿希望,收穫幸福的一年。可沒想到這一年的開始就如此的慘烈、痛苦。在此,博主真誠的祝福那些身處在抗疫一線的白衣天使們能夠平穩健康,給他(她)們致以最崇高的敬意」
這篇博客講述Python中的迭代器和生成器,內容較抽象,希望讀者結合代碼好好理解。

1. 迭代器

迭代是重複反饋過程的活動,其目的通常是爲了逼近所需目標或結果。
每一次對過程的重複稱爲一次“迭代”,而每一次迭代得到的結果會作爲下一次迭代的初始值。
在計算機中重複執行程序中的循環,直到滿足某條件爲止,亦稱爲迭代
在這裏插入圖片描述

1.1 iter()

Python語言中,在定義一個類時,如果在類中定義了iter()函數,
那麼這個類就是可迭代的類
由這個類所實例化的對象就是可迭代的對象
在Python語言中,可調用collections模塊的Iterable中的isinstance()函數判斷當前對象是否可迭代。

from collections import Iterable

class IterableClass(object):
	"""定義一個可迭代的類"""
    def __init__(self,name,nubmer):		# 構造函數
        self.name = name
        self.number = nubmer

    def __iter__(self):		# 定義iter函數,僞代碼
        pass

def main():
    test = IterableClass("tomato",2020)
    print("判斷test是否可迭代:%s" % isinstance(test,Iterable))

if __name__ == '__main__':
    main()

當我們運行上述代碼時,結果如下:
在這裏插入圖片描述
可當我們把定義的iter函數註釋掉後再運行時代碼,結果會大相徑庭。

# def __iter__(self):		# 定義iter函數,僞代碼
#        pass

在這裏插入圖片描述
由此可知:
當類中定義了iter函數時,那麼由該類實例化的對象是可迭代的。
當類中沒有定義iter函數時,由該類實例化的對象就不可迭代(例整型)。

1.2 next()

在類定義時,同時定義了iter函數和next函數的類,其所實例化的對象稱爲迭代器對象。
可以被next()函數調用並不斷返回下一個值的對象稱爲迭代器:Iterator
在Python語言中,可調用collections模塊的Iterable中的isinstance()函數判斷當前對象是否爲迭代器對象(代碼實現如上段)
接下來,我們在定義一個迭代器類。

from collections import Iterable

class IteratorClass(object):
	"""定義一個迭代器類"""
    def __init__(self):		# 構造函數
        self.g_number = 0
        self.name = list()
        self.number = list()

    def AddMemmber(self,name,number):	# 添加數據
        self.name.append(name)
        self.number.append(number)

    def __iter__(self):
        return self

    def __next__(self):
        if len(self.name) > self.g_number:
            name = self.name[self.g_number]
            number = self.number[self.g_number]
            self.g_number += 1
            return "姓名:"+name+", "+"學號:"+str(number)
        else:
            raise StopIteration

def main():
    test = IteratorClass()
    test.AddMemmber("tomato",2020)
    test.AddMemmber("potato",2021)
    test.AddMemmber("konato",2022)
    for member in test:
        print(member)

if __name__ == '__main__':
    main()

運行上段代碼,結果如以下圖示。
在這裏插入圖片描述
主線程執行順序:

  1. 定義一個迭代器類IteratorClass,實例化一個對象test
  2. 使用AddMemmber函數,將個人信息加入庫中
  3. 執行迭代運算,從test對象中取出每個人的個人信息
  4. 在迭代運算中(即for循環),迭代器對象會自動調用類中的iter函數,iter函數的返回值是一個迭代器。在此代碼中,test對象的iter函數的返回值爲自身,因爲test對象自身就是一個迭代器對象
  5. 調用迭代器的next函數來取值,一次迭代調用一次next函數。
  6. Python中的迭代器協議就是每次調用next函數的對象會前進到下一個結果,
    而在迭代器中的值取完時則會拋出StopIteration異常

2. 生成器

生成器是一種特殊的迭代器。
例:

列表生成式: [ x*2 for x in range()10 ]
列表生成器: ( x*2 for x in range()10 )

2.1 yield

在函數定義時,若函數體中存在關鍵字yield,
那麼該函數就是一個生成器模板
調用該函數,就是創建一個生成器對象
yield後面是誰,就把誰return,再次調用時從上次yield的地方繼續執行。
最後,我們用代碼來實現一下黃體字的編程邏輯:

g_number = 10		# 定義一個全局變量g_number

def generator():	# 定義一個生成器模板
    global g_number
    while True:
        print("----- 1 -----")
        print("當前number的值爲:",g_number)
        yield g_number
        g_number -= 1
        print("當前number的值爲:",g_number)
        print("----- 2 -----")

def main():
    test = generator()
    next(test)

if __name__ == '__main__':
    main()

因爲迭代器都能通過調用next()函數使其運行,
生成器是一種特殊的迭代器,
所以這裏的生成器對象test同樣調用next函數來運行。
運行上述代碼,結果如以下圖示:
在這裏插入圖片描述
當我們修改main函數,將next函數運行兩次,這時得到的結果如以下圖示:

def main():
    test = generator()
    next(test)
    next(test)

在這裏插入圖片描述
由此,我們可以看出在函數定義中,
yield後面是誰,就把誰return,再次調用時從上次yield的地方繼續執行,
當再次運行到yield時,再次將yield後面的值return。

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