深入了解PHP中生成器yield的使用_第1頁
深入了解PHP中生成器yield的使用_第2頁
深入了解PHP中生成器yield的使用_第3頁
深入了解PHP中生成器yield的使用_第4頁
深入了解PHP中生成器yield的使用_第5頁
已閱讀5頁,還剩3頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

第深入了解PHP中生成器yield的使用目錄1.什么是yield2.yield解決的問題3.yieldreturn的區(qū)別4.什么是yield選項(xiàng)5.生成器如果是做Python或者其他語言的小伙伴,對(duì)于生成器應(yīng)該不陌生。但很多PHP開發(fā)者或許都不知道生成器這個(gè)功能,可能是因?yàn)樯善魇荘HP5.5.0才引入的功能,也可以是生成器作用不是很明顯。但是,生成器功能的確非常有用。

1.什么是yield

生成器函數(shù)看上去就像一個(gè)普通函數(shù),除了不是返回一個(gè)值之外,生成器會(huì)根據(jù)需求產(chǎn)生更多的值。

看以下的例子:

functiongetValues(){

yield'value';

//輸出字符串"value"

echogetValues();

當(dāng)然,這不是他生效的方式,前面的例子會(huì)給你一個(gè)致命的錯(cuò)誤:類生成器的對(duì)象不能被轉(zhuǎn)換成字符串

2.yield解決的問題

解決運(yùn)行內(nèi)存的瓶頸,php程序中的變量存儲(chǔ)在內(nèi)存中,之前有遇到過讀取Excel文件時(shí)候,會(huì)出現(xiàn)內(nèi)存不足,出現(xiàn):

FatalError:Allowedmemorysizeofxxxxxxbytes

所以會(huì)設(shè)置php最大運(yùn)行內(nèi)存的設(shè)置:ini_set(memory_limit,200M)

但是當(dāng)我們讀取5g這么大的文件的時(shí)候,我們運(yùn)行內(nèi)存可能就吃不消了,所以會(huì)選擇yield

3.yieldreturn的區(qū)別

前面的錯(cuò)誤意味著getValues()方法不會(huì)如預(yù)期返回一個(gè)字符串,讓我們檢查一下他的類型:

functiongetValues(){

return'value';

var_dump(getValues());//string(5)"value"

functiongetValues(){

yield'value';

var_dump(getValues());//classGenerator#1(0){}

生成器類實(shí)現(xiàn)了生成器接口,這意味著你必須遍歷getValue()方法來取值:

foreach(getValues()as$value){

echo$value;

//使用變量也是好的

$values=getValues();

foreach($valuesas$value){

echo$value;

}

但這不是唯一的不同!

一個(gè)生成器運(yùn)行你寫使用循環(huán)來迭代一維數(shù)組的代碼,而不需要在內(nèi)存中創(chuàng)建是一個(gè)數(shù)組,這可能會(huì)導(dǎo)致你超出內(nèi)存限制。

在下面的例子里我們創(chuàng)建一個(gè)有800,000元素的數(shù)字同時(shí)從getValues()方法中返回他,同時(shí)在此期間,我們將使用函數(shù)memory_get_usage()來獲取分配給次腳本的內(nèi)存,我們將會(huì)每增加200,000個(gè)元素來獲取一下內(nèi)存使用量,這意味著我們將會(huì)提出四個(gè)檢查點(diǎn):

php

functiongetValues(){

$valuesArray=[];

//獲取初始內(nèi)存使用量

echoround(memory_get_usage()/1024/1024,2).'MB'.PHP_EOL;

for($i=1;$i800000;$i++){

$valuesArray[]=$i;

//為了讓我們能進(jìn)行分析,所以我們測(cè)量一下內(nèi)存使用量

if(($i%200000)==0){

//來MB為單位獲取內(nèi)存使用量

echoround(memory_get_usage()/1024/1024,2).'MB'.PHP_EOL;

return$valuesArray;

$myValues=getValues();//一旦我們調(diào)用函數(shù)將會(huì)在這里創(chuàng)建數(shù)組

foreach($myValuesas$value){}

前面例子發(fā)生的情況是這個(gè)腳本的內(nèi)存消耗和輸出:

0.34MB

8.35MB

16.35MB

32.35MB

這意味著我們的幾行腳本消耗了超過30MB的內(nèi)存,每次你你添加一個(gè)元素到$valuesArray數(shù)組中,都會(huì)增加他在內(nèi)存中的大小。

讓我們使用yield同樣的例子:

php

functiongetValues(){

//獲取內(nèi)存使用數(shù)據(jù)

echoround(memory_get_usage()/1024/1024,2).'MB'.PHP_EOL;

for($i=1;$i800000;$i++){

yield$i;

//做性能分析,因此可測(cè)量?jī)?nèi)存使用率

if(($i%200000)==0){

//內(nèi)存使用以MB為單位

echoround(memory_get_usage()/1024/1024,2).'MB'.PHP_EOL;

$myValues=getValues();//在循環(huán)之前都不會(huì)有動(dòng)作

foreach($myValuesas$value){}//開始生成數(shù)據(jù)

這個(gè)腳本的輸出令人驚訝:

0.34MB

0.34MB

0.34MB

0.34MB

這不意味著你從return表達(dá)式遷移到y(tǒng)ield,但如果你在應(yīng)用中創(chuàng)建會(huì)導(dǎo)致服務(wù)器上內(nèi)存出問題的巨大數(shù)組,則yield更加適合你的情況。

4.什么是yield選項(xiàng)

這里有很多yield的選項(xiàng),我將強(qiáng)調(diào)他們中的幾個(gè):

a.使用yield,你也可以使用return。

functiongetValues(){

yield'value';

return'returnValue';

$values=getValues();

foreach($valuesas$value){}

echo$values-getReturn();//'returnValue'

b.返回鍵值對(duì):

functiongetValues(){

yield'key'='value';

$values=getValues();

foreach($valuesas$key=$value){

echo$key.'='.$value;

}

5.生成器

1使用生成器來生成一個(gè)1到100的數(shù)組

functionmy_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){

}

可見是一個(gè)對(duì)象,是一個(gè)生成器對(duì)象,既然是對(duì)象那么也就是可以用foreach來遍歷

3遍歷生成器

foreach($arras$num){

echo$num.PHP_EOL;

}

看到可以完整遍歷出來,那么與那樣實(shí)現(xiàn)的不同地方,意義在哪里呢。重點(diǎn)來了。

4兩者內(nèi)存占用比較

上面已經(jīng)測(cè)試過使用數(shù)組的方式,隨著范圍的增大占用的內(nèi)存劇增,很快就超過了PHP的內(nèi)存上限。

那么使用生成器占用了多少內(nèi)存呢,來看看就知道了。

$start=memory_get_usage();

$arr=my_range(1,100);

$end=memory_get_usage();

echo$end-$start.'bytes'.PHP_EOL;

可以看到只占用了576bytes,當(dāng)然每個(gè)人測(cè)試的可能都會(huì)有點(diǎn)不同,環(huán)境不同,但是這不是重點(diǎn)。

我們?cè)賴L試增加數(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($arras$num){

echo$num.PHP_EOL;

}

這下我們就可以遍歷1到10000000的數(shù)字了,不相信內(nèi)存占用那么低的小伙伴,可以打開任務(wù)管理器毫無波瀾,即時(shí)再上調(diào)數(shù)字范圍。

5、生成器遍歷原理

生成器既

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論