mysql 生成数列_PHP生成器的创建和使用
1、概述
生成器是 PHP 5.5 引入的新特性,但是目測很少人用到它,其實(shí)這是個(gè)非常有用的功能。
生成器和迭代器有點(diǎn)類似,但是與標(biāo)準(zhǔn)的PHP迭代器不同,PHP生成器不要求類實(shí)現(xiàn)Iterator接口,從而減輕了類的開銷和負(fù)擔(dān)。生成器會(huì)根據(jù)需求每次計(jì)算并產(chǎn)出需要迭代的值,這對應(yīng)用的性能有很大的影響:試想假如標(biāo)準(zhǔn)的PHP迭代器經(jīng)常在內(nèi)存中執(zhí)行迭代操作,這要預(yù)先計(jì)算出數(shù)據(jù)集,性能低下;如果要使用特定方式計(jì)算大量數(shù)據(jù),如操作Excel表數(shù)據(jù),對性能影響更甚。此時(shí)我們可以使用生成器,即時(shí)計(jì)算并產(chǎn)出后續(xù)值,不占用寶貴的內(nèi)存空間。
2、創(chuàng)建生成器
生成器的創(chuàng)建方式很簡單,因?yàn)樯善骶褪荘HP函數(shù),只不過要在函數(shù)中一次或多次使用yield關(guān)鍵字。與普通的PHP函數(shù)不同的是,生成器從不返回值,只產(chǎn)出值。下面是一個(gè)簡單的生成器實(shí)現(xiàn):
function getLaravelAcademy() {yield 'http://LaravelAcademy.org';yield 'Laravel學(xué)院';yield 'Laravel Academy'; }很簡單吧!調(diào)用此生成器函數(shù)時(shí),PHP會(huì)返回一個(gè)屬于Generator類的對象,這個(gè)對象可以使用foreach函數(shù)迭代,每次迭代,PHP會(huì)要求Generator實(shí)例計(jì)算并提供下一個(gè)要迭代的值。生成器的優(yōu)雅體現(xiàn)在每次產(chǎn)出一個(gè)值之后,生成器的內(nèi)部狀態(tài)都會(huì)停頓;向生成器請求下一個(gè)值時(shí),內(nèi)部狀態(tài)又會(huì)恢復(fù)。生成器內(nèi)部的狀態(tài)會(huì)一直在停頓和恢復(fù)之間切換,直到抵達(dá)函數(shù)定義體的末尾或遇到空的return語句為止。我們可以使用下面的代碼調(diào)用并迭代上面定義的生成器:
foreach(getLaravelAcademy() as $yieldedValue) {echo $yieldedValue, PHP_EOL; }上面代碼輸出如下:
http://LaravelAcademy.org Laravel學(xué)院 Laravel Academy3、使用生成器
下面我們實(shí)現(xiàn)一個(gè)簡單的函數(shù)用于生成一個(gè)范圍內(nèi)的數(shù)值,以此說明生成器是如何節(jié)省內(nèi)存的。首先我們通過迭代器來實(shí)現(xiàn):
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; }此時(shí)執(zhí)行會(huì)報(bào)錯(cuò),提示超出單個(gè)PHP進(jìn)程內(nèi)存限制(要為100萬個(gè)數(shù)字提供內(nèi)存空間):
下面我們來改進(jìn)實(shí)現(xiàn)方案,使用生成器實(shí)現(xiàn)如下:
function makeRange($length) {for ($i=0; $i<$length; $i++) {yield $i;} }foreach (makeRange(1000000) as $i) {echo $i . PHP_EOL; }再次執(zhí)行就可以毫無壓力的打印出結(jié)果,因?yàn)樯善髅看沃恍枰獮橐粋€(gè)整數(shù)分配內(nèi)存。
此外,一個(gè)常用的使用案例就是使用生成器迭代流資源(文件、音頻等)。假設(shè)我們想要迭代一個(gè)大小為4GB的CSV文件,而虛擬私有服務(wù)器(VPS)只允許PHP使用1GB內(nèi)存,因此不能把整個(gè)文件都加載到內(nèi)存中,下面的代碼展示了如何使用生成器完成這種操作:
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); }上述示例一次只會(huì)為CSV文件中的一行分配內(nèi)存,而不會(huì)把整個(gè)4GB的CSV文件都讀取到內(nèi)存中。
4、總結(jié)
生成器是功能多樣性和簡潔性之間的折中方案,生成器只是向前進(jìn)的迭代器,這意味著不能使用生成器在數(shù)據(jù)集中執(zhí)行后退、快進(jìn)或查找操作,只能讓生成器計(jì)算并產(chǎn)出下一個(gè)值。迭代大型數(shù)據(jù)集或數(shù)列時(shí)最適合使用生成器,因?yàn)檫@樣占用的系統(tǒng)內(nèi)存最少。生成器也能完成迭代器能完成的簡單任務(wù),而且使用的代碼更少。
總而言之,生成器并沒有為PHP添加新功能,不過使用生成器大大簡化了某些任務(wù)
以上內(nèi)容希望幫助到大家,以上內(nèi)容希望幫助到大家,很多PHPer在進(jìn)階的時(shí)候總會(huì)遇到一些問題和瓶頸,業(yè)務(wù)代碼寫多了沒有方向感,不知道該從那里入手去提升,對此我整理了一些資料,包括但不限于:分布式架構(gòu)、高可擴(kuò)展、高性能、高并發(fā)、服務(wù)器性能調(diào)優(yōu)、TP6,laravel,YII2,Redis,Swoole、Swoft、Kafka、Mysql優(yōu)化、shell腳本、Docker、微服務(wù)、Nginx等多個(gè)知識(shí)點(diǎn)高級(jí)進(jìn)階干貨需要的可以免費(fèi)分享給大家,需要請戳這里獲取 或者請關(guān)注我的個(gè)人主頁以及知乎專欄
PHP7進(jìn)階架構(gòu)師?zhuanlan.zhihu.com總結(jié)
以上是生活随笔為你收集整理的mysql 生成数列_PHP生成器的创建和使用的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: pymysql安装_openstack
- 下一篇: python自带模块连接数据库_Pyth