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