小說python何時使用生成器

生成器、迭代器作爲python的兩個高級特性,相信大家肯定耳熟能詳,都能說道上一陣,但很多時候都是說說而已,知道有這麼個東西,而且是好東西,但再看看寫過的代碼,有多少確實使用它的?

一個語音特性,在潛意識中沒用被激活,更多時候還是因爲不知道它的應用場景,這裏就從三個方面說說生成器什麼時候應該用,而且必須用。

是否需要返回列表中的所有元素?

不需要

當做出不需要的回答時,就應該選擇生成器,而不是列表,因爲生成器的主要特性就是'lazy evaluation'

生成器,只有在真正需要時才生成結果,因此在不需要列表中的所有元素,自然是沒必要去創建它們的,創建後還不用,那就是浪費資源,而且影響效率

例如,我們碰到如下場景,公司年會搞一個抽獎活動,規則是每人拿一個號,抽獎時根據這些號碼搖號,搖出的號和你對應的號一致,那就表示中獎。

下面給出一個簡單實現:

import time
import random

def gen_winning_numbers():
    random.seed()
    elements = []
    for i in range (0,10):
        time.sleep(1) # 模擬很牛逼的搖號算法但有些費時
        elements.append(random.randint(1,10))

    return elements

random.seed()
my_number = random.randint(1,10)
print ("my number is " + str(my_number))

for winning_number in gen_winning_numbers():
    print(winning_number)
    if my_number == winning_number:
        print ("you win!")
        break

gen_winning_numbers函數是一個比較耗時的函數,隨機產生10箇中獎號碼,如果my_number在這10個數中,表示中獎且程序退出,從這個實現中可以看到,不管如何至少需要等10s,才知道中獎結果。

而往往只要有一箇中獎號碼和my_number一致,就表示中獎,就無需關心其他中獎號碼,也沒必要生成其他剩餘的號碼,最優情況下,只需要1s就得到中獎結果了

使用生成器就很容易解決這個問題

import time
import random

def gen_winning_numbers():
    random.seed()
    for i in range(0,10):
        time.sleep(1)  # 模擬很牛逼的搖號算法但有些耗時
        yield random.randint(1,10)

random.seed()
my_number = random.randint(1,10)
print ("my number is " + str(my_number))

for winning_number in gen_winning_numbers():
    print(winning_number)
    if my_number == winning_number:
        print ("you win!")
        break

函數是否需要大內存?

需要

當做出需要的回答時,就應該選擇生成器,因爲生成器在需要時創建,獲取到結果時纔開始處理,完成後在請求其他項目前可從內存中刪除,釋放內存

先看看下面這段代碼

def get_elements():
    elements = []
    for i in range (0,10000):
        elements.append("x"*10240)
    # 返回1W個每個元素10KB的大列表
    return elements

characters_count = 0

my_elements=get_elements()

for i in my_elements:
    characters_count = characters_count + len(i)

print(characters_count)

這段代碼每次執行時至少需要佔用超過100M的內存,而如果使用生成器,可是另外一番景象

def get_elements():
    for i in range (0,10000):
        yield("x"*10240)

characters_count = 0

my_elements=get_elements()

for i in my_elements:
    characters_count = characters_count + len(i)

print(characters_count)

得到同樣的結果,但只需要10KB的內存

列表生成過程中是否需要通知?

需要

當做出需要的回答時,就應該選擇生成器

在一個複雜或是耗時相對較長的列表生成過程中,用戶如果不知道當前的元素過程,一味的盲目等待,那應該是很煩人的、無法接受的。

例如,下面這個過程

import time

def elements():
    elements = []
    for i in range (0,4):
        # 模擬耗時操作
        time.sleep(5)
        elements.append(i)
    return elements

print("start")
print(elements())
print("end")

每次需要得到5個結果,必須得等待20s,更糟糕的是,在等待的過程中什麼都做不了,也不知內部具體情況,哪怕給個進度提示也好

import time

def elements():
    elements = []
    for i in range (0,4):
        # 模擬耗時操作
        time.sleep(5)
        yield(i)

print("start")
for i in elements():
    # 輸出一個簡易進度
    print(".", end="", flush=True)
print()
print("end")

由上可知:

如果創建一個元素的函數很耗時,如果該函數對內存佔用敏感,或是不需要列表中的所有元素,那麼最佳選擇是生成器,那其他情況下,都可以使用列表,對吧?

當然沒問題,但是如果選擇生成器是否更好呢,既擁有了上述優勢,也不乏列表的熟悉味道,因爲生成器轉換成列表很簡單

1. list方法

mylist = list(my_generator())

2. 列表生成式

mylist = [elem for elem in my_generator()]
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章