(PHP 5 >= 5.5.0, PHP 7, PHP 8)
生成器提供了一種更容易的方法來(lái)實(shí)現簡(jiǎn)單的對象迭代,相比較定義類(lèi)實(shí)現 Iterator 接口的方式,性能開(kāi)銷(xiāo)和復雜性大大降低。
生成器允許你在 foreach 代碼塊中寫(xiě)代碼來(lái)迭代一組數據而不需要在內存中創(chuàng )建一個(gè)數組, 那會(huì )使你的內存達到上限,或者會(huì )占據可觀(guān)的處理時(shí)間。相反,你可以寫(xiě)一個(gè)生成器函數,就像一個(gè)普通的自定義函數一樣, 和普通函數只返回一次不同的是, 生成器可以根據需要 yield 多次,以便生成需要迭代的值。
一個(gè)簡(jiǎn)單的例子就是使用生成器來(lái)重新實(shí)現 range() 函數。 標準的 range() 函數需要在內存中生成一個(gè)數組包含每一個(gè)在它范圍內的值,然后返回該數組, 結果就是會(huì )產(chǎn)生多個(gè)很大的數組。 比如,調用 range(0, 1000000) 將導致內存占用超過(guò) 100 MB。
做為一種替代方法, 我們可以實(shí)現一個(gè) xrange()
生成器, 只需要足夠的內存來(lái)創(chuàng )建
Iterator 對象并在內部跟蹤生成器的當前狀態(tài),這樣只需要不到1K字節的內存。
示例 #1 將 range() 實(shí)現為生成器
<?php
function xrange($start, $limit, $step = 1) {
if ($start <= $limit) {
if ($step <= 0) {
throw new LogicException('Step must be positive');
}
for ($i = $start; $i <= $limit; $i += $step) {
yield $i;
}
} else {
if ($step >= 0) {
throw new LogicException('Step must be negative');
}
for ($i = $start; $i >= $limit; $i += $step) {
yield $i;
}
}
}
/*
* 注意下面range()和xrange()輸出的結果是一樣的。
*/
echo 'Single digit odd numbers from range(): ';
foreach (range(1, 9, 2) as $number) {
echo "$number ";
}
echo "\n";
echo 'Single digit odd numbers from xrange(): ';
foreach (xrange(1, 9, 2) as $number) {
echo "$number ";
}
?>
以上例程會(huì )輸出:
Single digit odd numbers from range(): 1 3 5 7 9 Single digit odd numbers from xrange(): 1 3 5 7 9