文件介紹說道:生成器函式的核心是yield關鍵字。它最簡單的呼叫形式看起來像乙個return申明,不同之處在於普通return會返回值並終止函式的執行,而yield會返回乙個值給迴圈呼叫此生成器的**並且只是暫停執行生成器函式。
說了這麼多到底是個東西呢,只有自己親自動手寫**才知道。
1、首先看下我們常用的乙個產生陣列的函式range()
$ran
=range(1
,100);
var_dump
($ran
)//可以看到是乙個產生了乙個陣列
//既然是陣列就來遍歷看下效果吧
foreach
(range(1
,100)as
$num
)
2、現在我們自己來實現這個range()函式
function
my_range
($start
,$limit
)return
$arr
;}
了解了這個函式構造後,發現並沒有什麼神奇的地方,那生成器和這個有什麼關係呢,繼續往下看。
1、當我們遍歷的範圍很小的時候還看不到什麼問題,當我們要遍歷的數字很大就會超過php的記憶體限制,這下使用生成器就非常有必要了。
2、我們先看上面的range(1, 100)產生的陣列占用了多少記憶體
$start
=memory_get_usage()
;echo
$start
.' bytes'
.php_eol
;$arr
=range(1
,100);
$end
=memory_get_usage()
;echo
$end
-$start
.' bytes'
.php_eol
;
結果為:8280 bytes
3、試著增大數字的範圍可以看到占用的記憶體越來越大,下面是我的一組在cli模式測試的占用記憶體情況
// 10 728 bytes
// 100 8280 bytes
// 1000 36952 bytes
// 10000 528472 bytes
// 100000 6291568 bytes
// 1000000 35651696 bytes
如果繼續增加到10000000,就會報錯。根據個人設定php記憶體上限而定。我設定的是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、如果我們就是要操作很大的數字遍歷,除了調整記憶體限制,就無計可施了嘛,這下我們的生成器就要隆重登場了。
1、上面我們自己實現了range()方法,這次我們重新使用生成器來實現這個方法
function
my_range
($start
,$limit
)}
2、列印出來,看下返回究竟是什麼
$arr
=my_range(1
,100);
var_dump
($arr
);
結果是:
object(generator)#1 (0)
可見是乙個物件,是乙個生成器物件,既然是物件那麼也就是可以用foreach來遍歷
3、遍歷生成器
foreach
($arr
as$num
)
看到可以完整遍歷出來,那麼與那樣實現的不同地方,意義在**呢。重點來了。
4、兩者記憶體占用比較
上面已經測試過使用陣列的方式,隨著範圍的增大占用的記憶體劇增,很快就超過了php的記憶體上限。
那麼使用生成器占用了多少記憶體呢,來看看就知道了。
$start
=memory_get_usage()
;$arr
=my_range(1
,100);
$end
=memory_get_usage()
;echo
$end
-$start
.' bytes'
.php_eol
;
可以看到只占用了576bytes,當然每個人測試的可能都會有點不同,環境不同,但是這不是重點。
我們再嘗試增加數字範圍,可以看到數字範圍並沒有影響到記憶體占用,也就是可以輕鬆的遍歷超大數字。
$start
=memory_get_usage()
;$arr
=my_range(1
,100000000);
$end
=memory_get_usage()
;echo
$end
-$start
.' bytes'
.php_eol
;foreach
($arr
as$num
)
這下我們就可以遍歷1到10000000的數字了,不相信記憶體占用那麼低的小夥伴,可以開啟任務管理器毫無波瀾,即時再上調數字範圍。
5、生成器遍歷原理
生成器既然這麼強大,那麼他的遍歷原理是什麼呢。使用foreach遍歷的時候,相當於生成器執行了以下操作。
while
($arr
->
valid()
)//$arr->valid() 判斷生成器是否關閉
//$arr->current() 返回當前物件
//$arr->next() 繼續往下執行生成器
你以為生成器就只有這些用處嗎,當然不止。可以使用在很多大量資料的獲取場景中,一次性從資料庫讀取超多的資料,一次性從文字讀取超多行文字,都可以這樣處理。
不僅用於解決記憶體問題,還有其他的用武之地,只因本人才疏學淺只能先探索這麼多了。
生成器 PHP的生成器yield 原創
在php 5.5中,php多了乙個新的特性,那就是生成器 generator 生成器提供了一種更簡單的方法來實現簡單的物件迭代。下面的manual的引用 生成器提供了一種更容易的方法來實現簡單的物件迭代,相比較定義類實現 iterator 介面的方式,效能開銷和複雜性大大降低。生成器允許你在 for...
generator生成器與yield
普通函式 一路執行到底 generator函式 可以暫停執行 yield是什麼 yield是es6的新關鍵字,使生成器函式執行暫停,yield關鍵字後面的表示式的值返回給生成器的呼叫者。它可以被認為是乙個基於生成器的版本的return關鍵字。yield關鍵字實際返回乙個iteratorresult ...
Python之生成器(yield)
這裡是一段防爬蟲文字,請讀者忽略。本文原創首發於csdn,作者idys 部落格首頁 生成器函式 迭代器一定是可迭代物件,可迭代物件不一定是迭代器 def inc for i in range 5 yield i print type inc print type inc x inc print ty...