PHP 生成器Generators的入門理解和學習
阿新 • • 發佈:2018-11-19
什麼是生成器Generators
生成器允許你在 foreach 程式碼塊中寫程式碼來迭代一組資料而不需要在記憶體中建立一個數組, 那會使你的記憶體達到上限,或者會佔據可觀的處理時間。相反,你可以寫一個生成器函式,就像一個普通的自定義函式一樣, 和普通函式只返回一次不同的是, 生成器可以根據需要 yield 多次,以便生成需要迭代的值。
一個簡單的例子就是使用生成器來重新實現 range() 函式。 標準的 range() 函式需要在記憶體中生成一個數組包含每一個在它範圍內的值,然後返回該陣列, 結果就是會產生多個很大的陣列。 比如,呼叫 range(0, 10000) 將導致記憶體佔用超過 4 MB。
例子程式碼
<?php /** * Created by PhpStorm. * User: [email protected] * Date: 2018/7/30 * Time: 上午11:29 */ $start = xdebug_memory_usage(); $num = 10000; function rangeWithGenerators($start, $limit, $step = 1) { if ($start < $limit) { if ($step <= 0) { throw new LogicException('Step must be +ve'); } for ($i = $start; $i <= $limit; $i += $step) { yield $i; } } else { if ($step >= 0) { throw new LogicException('Step must be -ve'); } for ($i = $start; $i >= $limit; $i += $step) { yield $i; } } } if ($argc === 1) { $iterate = rangeWithGenerators(0, $num, 1); foreach ($iterate as $value){ echo $value . "\n"; } //var_dump(iterator_to_array($iterate)); } if ($argc === 2) { $test = range(0, $num, 1); foreach ($test as $value) { echo $value . "\n"; } } $end = xdebug_memory_usage(); echo sprintf("記憶體消耗量%s\n", convert($end-$start)); function convert($size){ $unit=array('b','kb','mb','gb','tb','pb'); return @round($size/pow(1024,($i=floor(log($size,1024)))),2).' '.$unit[$i]; }
環境
- PHP7.1
- Xdebug
執行命令
- php test.php 結果返回:記憶體消耗量416 b
- php test.php range 結果返回:記憶體消耗量4 mb
測試結果論述
- 通過程式碼的執行,比較除了PHP標準函式rang()和自定義函式rangeWithGenerators()之間的異同。實現了同樣的目的,卻消耗著不同的記憶體,生成器的優點顯而易見。
- rangeWithGenerators()使用了生成器,而生成器的關鍵就是使用yield關鍵詞,yield常見的使用涉及到foreach和for兩個流程控制語句。rangeWithGenerators()中for迴圈yield變數$i(yield可理解為生成-值,如同return可理解為返回-值)。
- rangeWithGenerators()函式返回的便是一個生成器Generators( 使用var_dump($iterate)檢視其型別 )。
- 既然rangeWithGenerators()函式返回的是一個生成器,我們可以使用以下兩種方式來使用:
- foreach迴圈該Generators,本例子中則使用該方法讀取Generators。
- PHP標準函式iterator_to_array(),該函式將Generators轉換為一個Array。
使用場景,可查閱參考資料2
參考資料:
http://php.net/manual/zh/lang...
實際生產中的使用
原文地址:https://segmentfault.com/a/1190000015879089