PHP yield简介
一、yield介紹
?文檔介紹說道:生成器函數(shù)的核心是yield關(guān)鍵字。它最簡單的調(diào)用形式看起來像一個return申明,不同之處在于普通return會返回值并終止函數(shù)的執(zhí)行,而yield會返回一個值給循環(huán)調(diào)用此生成器的代碼并且只是暫停執(zhí)行生成器函數(shù)。
?說了這么多到底是個東西呢,只有自己親自動手寫代碼才知道。
二、range函數(shù)探索
?1、首先看下我們常用的一個產(chǎn)生數(shù)組的函數(shù)range()
$ran = range(1, 100);var_dump($ran)//可以看到是一個產(chǎn)生了一個數(shù)組//既然是數(shù)組就來遍歷看下效果吧foreach (range(1, 100) as $num) { echo $num.PHP_EOL;}?2、現(xiàn)在我們自己來實(shí)現(xiàn)這個range()函數(shù)
function my_range($start,$limit){$arr = []; for($i=$start;$i<=$limit;$i++){$arr[] =$i;}return $arr;}?了解了這個函數(shù)構(gòu)造后,發(fā)現(xiàn)并沒有什么神奇的地方,那生成器和這個有什么關(guān)系呢,繼續(xù)往下看。
三、內(nèi)存占用
?1、當(dāng)我們遍歷的范圍很小的時候還看不到什么問題,當(dāng)我們要遍歷的數(shù)字很大就會超過PHP的內(nèi)存限制,這下使用生成器就非常有必要了。
?2、我們先看上面的range(1, 100)產(chǎn)生的數(shù)組占用了多少內(nèi)存
$start = memory_get_usage();echo $start.' bytes'.PHP_EOL;$arr = range(1, 100);$end = memory_get_usage();echo $end - $start .' bytes'.PHP_EOL;?結(jié)果為:8280 bytes
?3、試著增大數(shù)字的范圍可以看到占用的內(nèi)存越來越大,下面是我的一組在CLI模式測試的占用內(nèi)存情況
?如果繼續(xù)增加到10000000,就會報錯。根據(jù)個人設(shè)置PHP內(nèi)存上限而定。我設(shè)置的是512M。
Fatal error: Allowed memory size of 536870912 bytes exhausted (tried to allocate 536870920 bytes) in C:\wamp64\www\phpdemo\yield.php on line 31?4、如果我們就是要操作很大的數(shù)字遍歷,除了調(diào)整內(nèi)存限制,就無計可施了嘛,這下我們的生成器就要隆重登場了。
四、生成器
?1、上面我們自己實(shí)現(xiàn)了range()方法,這次我們重新使用生成器來實(shí)現(xiàn)這個方法
function my_range($start,$limit){ for($i=$start;$i<=$limit;$i++){yield $i;}}?2、打印出來,看下返回究竟是什么
$arr = my_range(1,100);var_dump($arr);?結(jié)果是:
object(Generator)#1 (0) {}?可見是一個對象,是一個生成器對象,既然是對象那么也就是可以用foreach來遍歷
?3、遍歷生成器
foreach($arr as $num){echo $num.PHP_EOL;}?看到可以完整遍歷出來,那么與那樣實(shí)現(xiàn)的不同地方,意義在哪里呢。重點(diǎn)來了。
?4、兩者內(nèi)存占用比較
??上面已經(jīng)測試過使用數(shù)組的方式,隨著范圍的增大占用的內(nèi)存劇增,很快就超過了PHP的內(nèi)存上限。
??那么使用生成器占用了多少內(nèi)存呢,來看看就知道了。
??可以看到只占用了576bytes,當(dāng)然每個人測試的可能都會有點(diǎn)不同,環(huán)境不同,但是這不是重點(diǎn)。
??我們再嘗試增加數(shù)字范圍,可以看到數(shù)字范圍并沒有影響到內(nèi)存占用,也就是可以輕松的遍歷超大數(shù)字。
$start = memory_get_usage();$arr = my_range(1, 100000000);$end = memory_get_usage();echo $end - $start .' bytes'.PHP_EOL;foreach($arr as $num){echo $num.PHP_EOL;}??這下我們就可以遍歷1到10000000的數(shù)字了,不相信內(nèi)存占用那么低的小伙伴,可以打開任務(wù)管理器毫無波瀾,即時再上調(diào)數(shù)字范圍。
?5、生成器遍歷原理
??生成器既然這么強(qiáng)大,那么他的遍歷原理是什么呢。使用foreach遍歷的時候,相當(dāng)于生成器執(zhí)行了以下操作。
五、結(jié)后語
??你以為生成器就只有這些用處嗎,當(dāng)然不止。可以使用在很多大量數(shù)據(jù)的獲取場景中,一次性從數(shù)據(jù)庫讀取超多的數(shù)據(jù),一次性從文本讀取超多行文本,都可以這樣處理。
??不僅用于解決內(nèi)存問題,還有其他的用武之地,只因本人才疏學(xué)淺只能先探索這么多了。
總結(jié)
以上是生活随笔為你收集整理的PHP yield简介的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 通过yum安装Oracle instan
- 下一篇: ThinkPHP3.2.3从php5升级