php生成器 yield 轉

2022-03-13 03:03:34 字數 3288 閱讀 4055

文件介紹說道:生成器函式的核心是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...