PHP生成器的創建和使用

PHP生成器的創建和使用

1、概述
生成器是 PHP 5.5 引入的新特性,但是目測很少人用到它,其實這是個非常有用的功能。

生成器和迭代器有點類似,但是與標準的PHP迭代器不同,PHP生成器不要求類實現Iterator接口,從而減輕了類的開銷和負擔。生成器會根據需求每次計算併產出需要迭代的值,這對應用的性能有很大的影響:試想假如標準的PHP迭代器經常在內存中執行迭代操作,這要預先計算出數據集,性能低下;如果要使用特定方式計算大量數據,如操作Excel表數據,對性能影響更甚。此時我們可以使用生成器,即時計算併產出後續值,不佔用寶貴的內存空間。

2、創建生成器
生成器的創建方式很簡單,因爲生成器就是PHP函數,只不過要在函數中一次或多次使用yield關鍵字。與普通的PHP函數不同的是,生成器從不返回值,只產出值。下面是一個簡單的生成器實現:

PHP生成器的創建和使用

很簡單吧!調用此生成器函數時,PHP會返回一個屬於Generator類的對象,這個對象可以使用foreach函數迭代,每次迭代,PHP會要求Generator實例計算並提供下一個要迭代的值。生成器的優雅體現在每次產出一個值之後,生成器的內部狀態都會停頓;向生成器請求下一個值時,內部狀態又會恢復。生成器內部的狀態會一直在停頓和恢復之間切換,直到抵達函數定義體的末尾或遇到空的return語句爲止。我們可以使用下面的代碼調用並迭代上面定義的生成器:

PHP生成器的創建和使用

上面代碼輸出如下:

PHP生成器的創建和使用

3、使用生成器
下面我們實現一個簡單的函數用於生成一個範圍內的數值,以此說明生成器是如何節省內存的。首先我們通過迭代器來實現:

PHP生成器的創建和使用

此時執行會報錯,提示超出單個PHP進程內存限制(要爲100萬個數字提供內存空間):

PHP生成器的創建和使用

下面我們來改進實現方案,使用生成器實現如下:

PHP生成器的創建和使用

再次執行就可以毫無壓力的打印出結果,因爲生成器每次只需要爲一個整數分配內存。

此外,一個常用的使用案例就是使用生成器迭代流資源(文件、音頻等)。假設我們想要迭代一個大小爲4GB的CSV文件,而虛擬私有服務器(VPS)只允許PHP使用1GB內存,因此不能把整個文件都加載到內存中,下面的代碼展示瞭如何使用生成器完成這種操作:

PHP生成器的創建和使用

上述示例一次只會爲CSV文件中的一行分配內存,而不會把整個4GB的CSV文件都讀取到內存中。

4、總結
生成器是功能多樣性和簡潔性之間的折中方案,生成器只是向前進的迭代器,這意味着不能使用生成器在數據集中執行後退、快進或查找操作,只能讓生成器計算併產出下一個值。迭代大型數據集或數列時最適合使用生成器,因爲這樣佔用的系統內存最少。生成器也能完成迭代器能完成的簡單任務,而且使用的代碼更少。

總而言之,生成器並沒有爲PHP添加新功能,不過使用生成器大大簡化了某些任務

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