php生成器使用總結

通常咱們在迭代一組數據的時候,須要建立一個數據,若是數組很大,則會消耗很大性能,甚至形成內存不足拋出error
好比:php

//Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 32 bytes) in D:\php\test\index.php on line 5
range(1, 100000000);

PHP5.5引入了迭代生成器的概念,迭代的概念早就在PHP有了,可是迭代生成器是PHP的一個新特性,這跟python3中的迭代生成器相似,看看PHP5.5的迭代生成器如何定義。
如下示例實現了生成器,每當產生一個數組元素則用yield關鍵詞返回,而且執行函數暫停,當執行函數next方法時,則會從上一次被yield的位置開始繼續執行,以下例子,只會產生中間變量$ipython

function xrange($start, $limit, $step = 1) {
    for ($i = $start; $i <= $limit; $i += $step) {
        yield $i;
    }
}
 
foreach (xrange(1, 9, 1) as $number) {
    echo "$number ";
}

這裏的xrange是一個迭代,功能和range是同樣的,若是使用range函數的話,那麼函數內部實現會儲存每一個迭代的中間過程,即每一箇中間變量都有 個內存空間,那麼首先程序使用的內存空間就大了,並且分配內存,回收內存都會致使程序的運行時間加長。可是若是使用上yield實現的xrange函數的 話,裏面全部的中間變量都只使用一個內存$i,這樣節省的時間和空間都會變小。數組

那麼爲何yield會有這樣的效果呢?聯想到lua中的yield,這裏就算是協程的概念了。在lua語言中,當程序運行到yield的時候,使用協程 將上下文環境記錄住,而後將程序操做權歸還到主函數,當主函數調用resume的時候,會從新喚起協程,讀取yield記錄的上下文。這樣造成了程序語言 級別的多協程操做。php 5.5這裏的yield也是一樣的道理,當程序運行到yield的時候,當前程序就喚起協程記錄上下文,而後主函數繼續操做,只是php中沒有使用如 resume同樣的關鍵字,而是「在使用的時候喚起」協程。好比上例中的foreach迭代器就能喚起yield。因此上面的這個例子就能理解了。函數

再好比:性能

function xrange($start, $end, $step = 1) {
    for ($i = $start; $i <= $end; $i += $step) {
      yield $i;
    }
}
foreach (xrange(1, 1000000) as $num) {
    echo $num, "\n";
}

注意關鍵字:yield,正是這個yeild關鍵字構建了一個迭代器,這個函數xrange跟以往的函數的不一樣之處就在這裏。通常狀況都是return一個值,而yield一個值就表示這是個迭代器,每循環一次這個迭代器就生成這個值,故名爲迭代生成器,迭代生成器這個函數能夠進行foreach循環,每次都產生一個值。大數據

PHP5.5以前是經過定義類實現Iterator接口的方式來構造迭代器,經過yield構造迭代器將更加提高性能節省系統開銷。lua

這種方法的優勢是顯而易見的.它可讓你在處理大數據集合的時候不用一次性的加載到內存中,甚至你能夠處理無限大的數據流。spa

如上面例子所示,這個迭代器的功能是生成從1到1000000的數字,循環輸出,那麼使用以往的方式是生成好這1到1000000的數字到數組中,將會十分佔用內存,由於是事先就要生成好全部結果,而不是用的時候按需生成,也就是說調用xrange這個迭代器的時候,裏面的函數尚未真正的運行,直到你每一次的迭代。code

相關文章
相關標籤/搜索