簡體   English   中英

Python生成器timeit

[英]Python generators timeit

我試圖理解許多教程中的Python生成器,而這些教程告訴他們它們比例如遍歷列表要快得多,所以我嘗試一下,編寫了一個簡單的代碼。 我沒想到時差會那么大,有人能解釋我為什么嗎? 也許我在這里做錯了。

def f(limit):
    for i in range(limit):
        if(i / 7.0) % 1 == 0:
            yield i

def f1(limit):
    l = []
    for i in range(limit):
        if(i / 7.0) % 1 == 0:
            l.append(i)
    return l


t = timeit.Timer(stmt="f(50)", setup="from __main__ import f")
print t.timeit()

t1 = timeit.Timer(stmt="f1(50)", setup="from __main__ import f1")
print t1.timeit()

結果:t = 0.565694382945 t1 = 11.9298217371

您沒有公平地比較ff1

您的第一個測試只是測量Python 構造生成器對象所花費的時間。 但是,它永遠不會迭代該對象,這意味着f內的代碼永遠不會實際執行(生成器僅在對其進行迭代時才執行其代碼)。

但是,您的第二項測試將測量調用f1所需的時間。 意思是,它計算函數構造列表l ,運行for循環直至完成,調用list.append多次,然后返回結果。 顯然,這將比僅生成生成器對象慢得多。

為了公平起見,將生成器f轉換為列表以使其耗盡:

t = timeit.Timer(stmt="list(f(50))", setup="from __main__ import f")

這將導致它被完全迭代,這意味着f的代碼現在將被執行。

您正在計時創建生成器對象所需的時間。 創建一個代碼實際上並不會執行任何代碼,因此實際上您正在計時一種精心設計的不執行任何操作的方法。

修復此問題后,您會發現生成器運行完成時通常會稍微慢一些。 它們的優勢在於,它們不需要一次將所有元素存儲在內存中,並且可以中途停止。 例如,當您有一系列布爾值並且要檢查它們是否為真時,使用列表時,首先要計算所有值並創建它們的列表,然后再檢查真值,而使用生成器時,您可以:

  • 創建第一個布爾值
  • 檢查是否為真,如果是,則停止創建布爾值
  • 否則,創建第二個布爾值
  • 檢查一個人是否正確,如果是,請停止創建布爾值
  • 等等。

https://wiki.python.org/moin/Generators在“提高性能”部分下有一些不錯的信息。 盡管創建一個生成器可能會花費一些時間,但它具有許多優點。

  • 使用更少的內存。 通過一一創建值,整個列表就永遠不會在內存中。
  • 開始的時間更少。 制作整個列表需要花費時間,而生成器可以在創建第一個值后立即使用。
  • 生成器沒有設定的終點。

這是一個有關創建生成器和迭代器的好教程, 網址為http://sahandsaba.com/python-iterators-generators.html 看看這個!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM