php生成器的使用

按照php的文档说明

一个生成器函数看起来像一个普通的函数,不同的是普通函数返回一个值,而一个生成器可以yield生成许多它所需要的值。
当一个生成器被调用的时候,它返回一个可以被遍历的对象.当你遍历这个对象的时候(例如通过一个foreach循环),PHP 将会在每次需要值的时候调用生成器函数,并在产生一个值之后保存生成器的状态,这样它就可以在需要产生下一个值的时候恢复调用状态。
一旦不再需要产生更多的值,生成器函数可以简单退出,而调用生成器的代码还可以继续执行,就像一个数组已经被遍历完了。

一个生成器不可以返回值: 这样做会产生一个编译错误。然而return空是一个有效的语法并且它将会终止生成器继续执行。

/**
 * 安原来的写法,我需要一个方法来整理数据。nums()会返回一个数组或者其他可以迭代的数据
 * 然后再遍历这个数组
 */
function nums() {
    $array = array();
    for ($i = 0; $i < 10000; ++$i) {
        $array[]= $i;
    }
    return $array;
}

foreach (nums() as $v){
    var_dump($v);
};


/**
 * 但是用了yield之后,我不再需要创建一个变量,来存储这个数据。
 * 而是在内部会为生成的值配对连续的整型索引,就像一个非关联的数组。 
 * 这样会省掉很大的内存开销
 */
function nums2() {
    for ($i = 0; $i < 10000; ++$i) {
        yield $i;
    }
}

foreach (nums2() as $v){
    var_dump($v);
};

如果需要在生成器中指定下标 可以 yield $id => $fields;

$handler=function() {
        $start = microtime(true);

        yield;

        $use_time = (microtime(true) - $start) * 1000;
        echo "the time is ".(int)$use_time."ms\n";
        
        yield;
        $use_time = (microtime(true) - $start) * 1000;
        echo "the time2 is ".(int)$use_time."ms\n";
};

//根据文档的说明 当一个生成器被调用的时候,它返回一个可以被遍历的对象.当你遍历这个对象的时候
//PHP 将会在每次需要值的时候调用生成器函数,
//也就是说此时并没有真的调用$handler中定义的函数。而是返回了一个生成器
$generator = call_user_func_array($handler,array());

if ($generator && $generator instanceof \Generator) {

    //当对生成器进行迭代的时候,才会真正的调用该$handler中定义的函数
    if ($generator->current() === false) {
        /***do some thing**/
    }
}

生成器也可以通过引用来使用

/**
 * 使用引用来生成值
 */
function &gen_reference() {
    $value = 3;

    while ($value > 0) {
        yield $value;
    }
}
/* 
 * 我们可以在循环中修改$number的值,而生成器是使用的引用值来生成,所以gen_reference()内部的$value值也会跟着变化。
 */
foreach (gen_reference() as &$number) {
    echo (--$number).'... ';
}

除了通过引用来改变生成器中的数据之外,我们还可以使用send方法传递数据

function printer() {
    while (true) {
        $string = yield; echo $string; } } $printer = printer(); $printer->send('Hello world!');

但是上面的例子如果没有 while(true),那么无论后面send多少次,该生成器只会执行一次。如此说来,似乎可以用这个来控制本函数调用的最多次数?

除了向里面传递数据之外,还可以throw异常。

function application() {
    while (true){
        try {
             yield;

        }catch (Exception $e){
            echo $e;
        }
    }
}

$printer = application();
$printer->throw(new  Exception("test"));

 

生成器的嵌套

/**
 * 在php7中 可以通过yield from 进行嵌套
 */
function count_to_ten() {
    yield 1;
    yield 2;
    yield from [3, 4];
    yield from new ArrayIterator([5, 6]);
    yield from seven_eight();
    yield 9;
    yield 10;
}

function seven_eight() {
    yield 7;
    yield from eight();
}

function eight() {
    yield 8;
}

$gen = count_to_ten();
foreach ($gen as $num) {
    echo "$num ";
}
echo "the return value is ".$gen->getReturn();

 

转载于:https://www.cnblogs.com/coder5/p/5422054.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值