PHP 新特性:生成器的創建和使用

碼農程序 / 2019-03-18 19:30:50

本公眾號只做學習分享,本公眾號會不定期的給大家分享視頻教學教程,項目源碼,文章最新動態等,感謝大家的支持!


抖音號startphp

用短視頻和大家分享PHP學習方法,學習技巧與經驗分享,

歡迎關注抖音號:startphp


教程力薦

要提升自己的學習能力的同學,自己還是要擁有一本屬于自己的書的,因為你在忘記的時候可以經常拿出來翻閱一下,鞏固一下。


文章內容

1、概述

生成器是 PHP 5.5 引入的新特性,但是目測很少人用到它,其實這是個非常有用的功能。

生成器和迭代器有點類似,但是與標準的PHP迭代器不同,PHP生成器不要求類實現Iterator接口,從而減輕了類的開銷和負擔。生成器會根據需求每次計算并產出需要迭代的值,這對應用的性能有很大的影響:試想假如標準的PHP迭代器經常在內存中執行迭代操作,這要預先計算出數據集,性能低下;如果要使用特定方式計算大量數據,如操作Excel表數據,對性能影響更甚。此時我們可以使用生成器,即時計算并產出后續值,不占用寶貴的內存空間。

2、創建生成器

生成器的創建方式很簡單,因為生成器就是PHP函數,只不過要在函數中一次或多次使用yield關鍵字。與普通的PHP函數不同的是,生成器從不返回值,只產出值。下面是一個簡單的生成器實現:

function getLaravelAcademy() {
    yield 'http://LaravelAcademy.org';
    yield 'Laravel學院';
    yield 'Laravel Academy';
}

很簡單吧!調用此生成器函數時,PHP會返回一個屬于Generator類的對象,這個對象可以使用foreach函數迭代,每次迭代,PHP會要求Generator實例計算并提供下一個要迭代的值。生成器的優雅體現在每次產出一個值之后,生成器的內部狀態都會停頓;向生成器請求下一個值時,內部狀態又會恢復。生成器內部的狀態會一直在停頓和恢復之間切換,直到抵達函數定義體的末尾或遇到空的return語句為止。我們可以使用下面的代碼調用并迭代上面定義的生成器:

foreach(getLaravelAcademy() as $yieldedValue) {
    echo $yieldedValue, PHP_EOL;
}


上面代碼輸出如下:

http://LaravelAcademy.org
Laravel學院
Laravel Academy

3、使用生成器

下面我們實現一個簡單的函數用于生成一個范圍內的數值,以此說明生成器是如何節省內存的。首先我們通過迭代器來實現:

function makeRange($length) {
    $dataSet = [];
    for ($i=0; $i<$length; $i++) {
        $dataSet[] = $i;
    }
    return $dataSet;
}

$customRange = makeRange(1000000);
foreach ($customRange as $i) {
    echo $i . PHP_EOL;
}


此時執行會報錯,提示超出單個PHP進程內存限制(要為100萬個數字提供內存空間):

下面我們來改進實現方案,使用生成器實現如下:

function makeRange($length) {
    for ($i=0; $i<$length; $i++) {
        yield $i;
    }
}

foreach (makeRange(1000000as $i) {
    echo $i . PHP_EOL;
}


再次執行就可以毫無壓力的打印出結果,因為生成器每次只需要為一個整數分配內存。

此外,一個常用的使用案例就是使用生成器迭代流資源(文件、音頻等)。假設我們想要迭代一個大小為4GB的CSV文件,而虛擬私有服務器(VPS)只允許PHP使用1GB內存,因此不能把整個文件都加載到內存中,下面的代碼展示了如何使用生成器完成這種操作:

function getRows($file) {
    $handle = fopen($file, 'rb');
    if ($handle == FALSE) {
        throw new Exception();
    }
    while (feof($handle) === FALSE) {
        yield fgetcsv($handle);
    }
    fclose($handle);
}

foreach ($getRows($file) as $row) {
    print_r($row);
}

上述示例一次只會為CSV文件中的一行分配內存,而不會把整個4GB的CSV文件都讀取到內存中。

4、總結

生成器是功能多樣性和簡潔性之間的折中方案,生成器只是向前進的迭代器,這意味著不能使用生成器在數據集中執行后退、快進或查找操作,只能讓生成器計算并產出下一個值。迭代大型數據集或數列時最適合使用生成器,因為這樣占用的系統內存最少。生成器也能完成迭代器能完成的簡單任務,而且使用的代碼更少。

總而言之,生成器并沒有為PHP添加新功能,不過使用生成器大大簡化了某些任務


以上是文章的全部內容,有需要交流與學習的,有需要視頻教程的可以上微店查看查看。



4399小游戏上海麻将连连看 平特一肖资料免费公开资料 上海快3今天推荐豹子 黑龙江快乐十分遗漏号码 老时时360开奖票 安徽时时计划 一码中特吧 辽宁35选7开奖2019年65期 重庆时时真的存在吗 曾道人开奖结果 大发快3豹子走势图