PHP生成器是5.5.0引入的功能。php
生成器實際上就是簡單的迭代器。函數
與標準的PHP迭代器不一樣,生成器不要求類實現Iterator接口,從而減輕了類的負擔。性能
生成器會根據需求計算產出迭代的值。而標準的PHP迭代器常常在內存中執行迭代操做,這要預先計算出數據集,性能較低。.net
若是使用特定的防禦計算大量數據,能夠使用生成器,即時計算併產出後續值,不佔用內存。code
生成器不能完成全部迭代器的操做。沒法後退,快進,而且生成器是一次性的,沒法對此迭代同一個生成器。對象
生成器從不返回值,只是產出值。接口
<?php function myGenerator() { yield 'v1'; yield 'v2'; yield 'v3'; }
調用生成器函數時,PHP會反悔一個屬於Generator
類的對象。這個對象是能夠foreach
迭代的。每次迭代,PHP要求這個實例計算並提供下一個要迭代的值。內存
每次產出一個值,生成器的內部狀態都會停頓。向生成器請求下一個值時,內部狀態纔會恢復。這種停頓-恢復的狀態會一直持續下去。get
<?php foreach (myGenerator() as $yieldValue) { echo $yieldValue , PHP_EOL; }
<?php function makeRange($length) { $dataset = []; for ($i = 0; $i < $length; $i++) { $dataset[] = $i; } return $dataset; } $customRange = makeRange(1000000); foreach ($customRange as $i) { echo $i, PHP_EOL; }
上面的這個方法並無善用內存,使用生成器只會爲一個整數分配內存。it
<?php function makeRange($length) { for ($i = 0; $i < $length; $i++) { yield $i; } } foreach(makeRange(1000000) as $i) { echo $i, PHP_EOL; }
再舉個例子:使用生成器處理CSV文件
<?php function getRows($file) { $handle = fopen($file, 'rb'); if ($handle === false) { throw new Exception(); } while (feof($handle) === false) { yield fgetcsv($handle); } fclose($handle); } foreach (getRows('data.csv') as $row) { print_r($row); }
這個例子中,生成器只會爲CSV文件分配一行內存,而不是讀入整個文件到內存。
若是須要更多功能,例如在數據集中執行後腿,快進或查找操做,最好本身編寫類,實現Iterator接口(http://php.net/manual/class.iterator.php),或者使用PHP標準庫中某個原生的迭代器(http://php.net/manual/spl.iterators.php)
參考:
Modern PHP