歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> php生成器的使用

php生成器的使用

日期:2017/3/1 9:16:37   编辑:Linux編程

按照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);
};

$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();

Copyright © Linux教程網 All Rights Reserved