[英]Are there any advantages of non-generator iterators over generators in Python?
在下面的代碼中, i1
是一個迭代器。
def sq(x):
y = []
for i in x:
y.append(i**2)
return y
l1 = range(5)
s1 = sq(l1)
i1 = iter(s1)
我可以為相同的平方運算編寫一個生成器。 在下面的代碼中, g1
是一個生成器。
def sqg(x):
for i in x:
yield i**2
g1 = sqg(l1)
我知道生成器使用更少的代碼並且更易於讀寫。 我知道生成器也運行得更快,因為它們保持本地狀態。
使用i1
優於g1
有什么優勢嗎?
當您調用sq(l1)
時,在sq
內部會填充一個列表y
。 這會消耗 memory,其大小與x
的大小成正比,一旦耗盡。
在第二種情況下,當您調用sqg(l1)
時, sqg
沒有任何用於存儲結果的內部列表。 它直接產生計算值,使得 memory 消耗常數並且與x
的大小無關。
至於非生成器迭代器相對於生成器的優勢,我認為沒有性能優勢,但可能存在結構優勢。 生成器(一種像您提到的迭代器)被定義為通過調用 function 返回的迭代器,其中包含yield
語句。 這意味着您不能向代表生成器的 object 添加任何可調用的其他方法,因為這種特殊類型的迭代器是隱式提供給您的。
另一方面,迭代器有一個更寬松的定義:一個 object 帶有一個__next__
方法和一個返回self
的__iter__
方法。 您可以創建一個 class Squares
遵循前面的迭代器標准,並且為了獲得該迭代器的實例,您必須顯式實例化Squares
。 因為您可以控制返回給您的迭代器的屬性,所以您可以添加返回該迭代器的內部 state 的實例方法,這些方法不是通過__next__
表示的,而使用生成器時,您會被鎖定到隱式提供給您的生成器 object 中。 通常,生成器會完成這項工作,但有時您需要使用非生成器迭代器來獲得超越__next__
提供的功能所需的控制。
在這種特定情況下,我認為您不需要通過使用非生成器迭代器給予您顯式控制,因此使用生成器會更好。
創建列表s1
優於生成器的優點 - 它具有定義的長度,您可以對其進行索引和切片,並且可以多次迭代它而無需重新創建它。 不過,也許您不會將這些視為非生成器迭代器的優勢。
另一個區別是,基於列表的迭代器涉及預先完成所有工作,然后緩存結果,而生成器一次完成工作。 如果處理任務是資源密集型的,那么列表方法會在生成列表時導致初始暫停,然后運行速度更快(因為您只需從 memory 檢索結果;還要考慮結果可以緩存在文件中, 例如)。 生成器方法不會有初始暫停,但會在生成每個結果時運行得更慢。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.