中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

PHP中生成器yield怎么使用

發布時間:2022-07-19 13:42:45 來源:億速云 閱讀:143 作者:iii 欄目:開發技術

這篇文章主要介紹了PHP中生成器yield怎么使用的相關知識,內容詳細易懂,操作簡單快捷,具有一定借鑒價值,相信大家閱讀完這篇PHP中生成器yield怎么使用文章都會有所收獲,下面我們一起來看看吧。

1. 什么是 "yield"

生成器函數看上去就像一個普通函數, 除了不是返回一個值之外, 生成器會根據需求產生更多的值。

看以下的例子:

function getValues() {
    yield 'value';
}

// 輸出字符串 "value"
echo getValues();

當然, 這不是他生效的方式, 前面的例子會給你一個致命的錯誤: 類生成器的對象不能被轉換成字符串

2.yield 解決的問題

解決運行內存的瓶頸,php程序中的變量存儲在內存中,之前有遇到過讀取Excel文件時候,會出現內存不足,出現:

Fatal Error: Allowed memory size of xxxxxx bytes 

所以會設置php 最大運行內存的設置: ini_set('memory_limit', '200M')

但是當我們讀取5g 這么大的文件的時候,我們運行內存可能就吃不消了,所以會選擇yield

3."yield" & "return" 的區別

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

function getValues() {
    return 'value';
}
var_dump(getValues()); // string(5) "value"

function getValues() {
    yield 'value';
}
var_dump(getValues()); // class Generator#1 (0) {}

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

foreach (getValues() as $value) {
   echo $value;
}

// 使用變量也是好的
$values = getValues();
foreach ($values as $value) {
   echo $value;
}

但這不是唯一的不同!

一個生成器運行你寫使用循環來迭代一維數組的代碼,而不需要在內存中創建是一個數組,這可能會導致你超出內存限制。

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

<?php
function getValues() {
   $valuesArray = [];
   // 獲取初始內存使用量
   echo round(memory_get_usage() / 1024 / 1024, 2) . ' MB' . PHP_EOL;
   for ($i = 1; $i < 800000; $i++) {
      $valuesArray[] = $i;
      // 為了讓我們能進行分析,所以我們測量一下內存使用量
      if (($i % 200000) == 0) {
         // 來 MB 為單位獲取內存使用量
         echo round(memory_get_usage() / 1024 / 1024, 2) . ' MB'. PHP_EOL;
      }
   }
   return $valuesArray;
}
$myValues = getValues(); // 一旦我們調用函數將會在這里創建數組
foreach ($myValues as $value) {}

前面例子發生的情況是這個腳本的內存消耗和輸出:

0.34 MB
8.35 MB
16.35 MB
32.35 MB

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

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

<?php
function getValues() {
   // 獲取內存使用數據
   echo round(memory_get_usage() / 1024 / 1024, 2) . ' MB' . PHP_EOL;
   for ($i = 1; $i < 800000; $i++) {
      yield $i;
      // 做性能分析,因此可測量內存使用率
      if (($i % 200000) == 0) {
         // 內存使用以 MB 為單位
         echo round(memory_get_usage() / 1024 / 1024, 2) . ' MB'. PHP_EOL;
      }
   }
}
$myValues = getValues(); // 在循環之前都不會有動作
foreach ($myValues as $value) {} // 開始生成數據

這個腳本的輸出令人驚訝:

0.34 MB
0.34 MB
0.34 MB
0.34 MB

這不意味著你從 return 表達式遷移到 yield,但如果你在應用中創建會導致服務器上內存出問題的巨大數組,則 yield 更加適合你的情況。

4. 什么是 "yield" 選項

這里有很多 yield 的選項, 我將強調他們中的幾個:

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

function getValues() {
   yield 'value';
   return 'returnValue';
}
$values = getValues();
foreach ($values as $value) {}
echo $values->getReturn(); // 'returnValue'

b. 返回鍵值對:

function getValues() {
   yield 'key' => 'value';
}
$values = getValues();
foreach ($values as $key => $value) {
   echo $key . ' => ' . $value;
}

5. 生成器

1 使用生成器來生成一個1到100的數組

function  my_range($start,$limit){    
    for($i=$start;$i<=$limit;$i++){
        yield $i;
    }
}

2 打印出來,看下返回究竟是什么

$arr = my_range(1,100);
var_dump($arr);

結果是:

object(Generator)#1 (0) {
}

可見是一個對象,是一個生成器對象,既然是對象那么也就是可以用foreach來遍歷

3 遍歷生成器

foreach($arr as $num){
    echo $num.PHP_EOL;
}

看到可以完整遍歷出來,那么與那樣實現的不同地方,意義在哪里呢。重點來了。

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){
    echo $num.PHP_EOL;
}

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

5、生成器遍歷原理

生成器既然這么強大,那么他的遍歷原理是什么呢。使用foreach遍歷的時候,相當于生成器執行了以下操作。

while($arr->valid()){
    echo $arr->current().PHP_EOL;
    $arr->next();
}
//$arr->valid()     判斷生成器是否關閉
//$arr->current() 返回當前對象
//$arr->next()    繼續往下執行生成器

關于“PHP中生成器yield怎么使用”這篇文章的內容就介紹到這里,感謝各位的閱讀!相信大家對“PHP中生成器yield怎么使用”知識都有一定的了解,大家如果還想學習更多知識,歡迎關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

武城县| 宁都县| 江永县| 育儿| 延边| 康保县| 邯郸市| 阿坝| 长武县| 青龙| 德庆县| 德安县| 玉树县| 梁山县| 吉木萨尔县| 宁乡县| 大洼县| 通山县| 巴塘县| 沈阳市| 九江市| 荥阳市| 云梦县| 佛山市| 富源县| 广南县| 沙湾县| 涞源县| 贵南县| 镇远县| 镇安县| 高要市| 于都县| 广宗县| 峨边| 永胜县| 南木林县| 龙山县| 山阴县| 册亨县| 鸡西市|