引用手册:一个生成器函数看起来像一个普通的函数,不同的是普通函数返回一个值,而一个生成器可以yield生成许多它所需要的值。当一个生成器被调用的时候,它返回一个可以被遍历的对象.当你遍历这个对象的时候(例如通过一个foreach循环),PHP 将会在每次需要值的时候调用生成器函数,并在产生一个值之后保存生成器的状态,这样它就可以在需要产生下一个值的时候恢复调用状态。
以下这句话会让让上面手册的内容更加的理解明白。
yield关键字 :生成器函数的核心是yield关键字。它最简单的调用形式看起来像一个return申明,不同之处在于普通return会返回值并终止函数的执行,而yield会返回一个值给循环调用此生成器的代码并且只是暂停执行生成器函数。
为什么要用生成器?手册上说道,一个简单的例子就是使用生成器来实现range函数;因为如果使用range函数生成一个很大的数组的时候,那么占用内存是非常大的,所以使用生成器可以很好的解决这个问题。
注:请使用5.4以上版本
我在这里使用手册里面的例子来说明一下使用生成器实现range函数;在这里我把手册的演示删除了一点代码,这样就可以专注来说生成器了:
先看一个最简单的例子:
<?php
//定一个函数
function gen_one_to_three() {
//for循环
for ($i = 1; $i <= 3; $i++) {
//注意变量$i的值在不同的yield之间是保持传递的。
yield $i;
}
}
//yield会返回一个值给循环调用此生成器的代码并且只是暂停执行生成器函数。
$generator = gen_one_to_three();
foreach ($generator as $value) {
echo "$value\n";
}
?>
随后输出了 1 2 3
我们再看以下xrange实现(我删掉了一些代码):
<?php
//定义xrange函数
function xrange($start, $limit, $step = 1) {
//如果start小于limit那么就
if ($start < $limit) {
//yield会返回一个值给循环调用此生成器的代码并且只是暂停执行生成器函数。
for ($i = $start; $i <= $limit; $i += $step) {
yield $i;
}
} else {
//yield会返回一个值给循环调用此生成器的代码并且只是暂停执行生成器函数。
for ($i = $start; $i >= $limit; $i += $step) {
yield $i;
}
}
}
/*
* 注意下面range()和xrange()输出的结果是一样的。
*/
echo 'Single digit odd numbers from range(): ';
//在这里使用range函数
foreach (range(1, 9, 2) as $number) {
echo "$number ";
}
echo "<br/>";
echo 'Single digit odd numbers from xrange(): ';
//在这里我们使用自定义的xrange
//注意:yield会返回一个值给循环调用此生成器的代码并且只是暂停执行生成器函数。
//所以她们的输出是相同的
foreach (xrange(1, 9, 2) as $number) {
echo "$number ";
}
?>
输出如下如下:
生成一个键值对:这里使用的也是php手册里面的例子,在这里我把解释写在了代码的注释中了
<?php
/*
* 下面每一行是用分号分割的字段组合,第一个字段将被用作键名。
*/
//input变量
$input = <<<'EOF'
1;PHP;Likes dollar signs
2;Python;Likes whitespace
3;Ruby;Likes blocks
EOF;
//定义方法 参数为input
function input_parser($input) {
foreach (explode("\n", $input) as $line) {//使用explode方法用\n分隔$input字符串为数组 并且使用了foreach
$fields = explode(';', $line); //分隔$line的值,此时line的值中例如 1;PHP;Likes dollar signs 用分号分隔为数组
$id = array_shift($fields);//使用array_shift删除数组的第一个值并且返回,那么如上注释中说的,那么此时应该id就是1
yield $id => $fields; //返回键值对
}
}
//调用input_parser函数,传入input
foreach (input_parser($input) as $id => $fields) {
echo "$id:\n";
echo " $fields[0]\n";
echo " $fields[1]\n";
}
?>
运行如下:
身体不适。。。运动过度。。。今天就一篇吧。。。