生成器和迭代器有点类似,但是与标准的PHP迭代器不同,PHP生成器不要求类实现Iterator接口,从而减轻了类的开销和负担。生成器会根据需求每次计算并产出需要迭代的值,这对应用的性能有很大的影响:试想假如标准的PHP迭代器经常在内存中执行迭代操作,这要预先计算出数据集,性能低下;如果要使用特定方式计算大量数据,如操作Excel表数据,对性能影响更甚。此时我们可以使用生成器,即时计算并产出后续值,不占用宝贵的内存空间。
生成器也是一个函数,不同的是这个函数的返回值是依次返回,而不是只返回一个单独的值.或者,换句话说,生成器使你能更方便的实现了迭代器接口.
实例1:
1 2 3 4 5 6 7 8
| function crange($number) { $data = []; for($i=0;$i<$number;$i++) { $data[] = time(); } return $data; }
|
上面是一个普通的生成数组的函数,我们调用 crange(10) 也是正常,但是如果我们传递的参数是*crange(10000000)*的时候就会发现,如下:
内存崩了,解决这个问题,优化一下:
1 2 3 4 5 6
| function crange($number){ for($i=0;$i<$number;$i++){ yield $i; } }
|
如上代码所示,使用关键字 yield。
1 2 3 4 5 6
| $data = crange(10000000);
foreach($data as $num) { var_dump($num); }
|
上面函数毫无压力的打印出结果,因为生成器每次只需要为一个整数分配内存。
实例2:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| $input = <<<EOF 1;PHP-全世界最好的语言 2;Python-这个没得说了 3;Ruby-我不认识他 EOF; function input_parser($input) { foreach (explode("\n", $input) as $line) { $fields = explode(';', $line); $id = array_shift($fields); yield $id => $fields; } }
foreach (input_parser($input) as $id => $fields) { echo "$id:\n"; echo " $fields[0]\n"; }
|
实例3:
1 2 3 4 5 6 7 8 9 10 11
| function xrange($number) { for($i=1;$i<=$number;$i++) { yield $i; } } $data = xrange(10000000); foreach($data as $k=>$val) { echo $val."\n"; }
|
上面几个实例,看了的文都会说,大爷的,没啥实际意义,接下来我们看看下面几个例子:
实例4:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
|
function get_log($path) { $result = fopen($path,'a+'); try { while (!feof($result)) { $line = fgets($result); var_dump($line); } } finally { fclose($result); } }
get_log('./error.log');
function get_log_y($path) { $result = fopen($path,'a+'); try { while (!feof($result)) { yield fgets($result); } } finally { fclose($result); } }
$data = get_log_y('./error.log'); foreach ($data as $val) { echo $val; }
|