亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > PHP > 正文

淺談一下PHP生成器的使用方法

2020-03-22 18:07:01
字體:
來源:轉載
供稿:網友
PHP 在 5.5 版本中引入了「生成器(Generator)」特性,不過這個特性并沒有引起人們的注意。在官方的 從 PHP 5.4.x 遷移到 PHP 5.5.x 中介紹說它能以一種簡單的方式實現迭代器(Iterator)。但是,除此之外,生成器又可以在哪些場景下使用?

生成器實現通過 yield 關鍵字完成。生成器提供一種簡單的方式實現迭代器,幾乎無任何額外開銷或需要通過實現迭代器接口的類這種復雜方式實現迭代。

文檔提供了一個簡單的實例演示這個簡單的迭代器,請看下面的代碼:

function xrange($start, $limit, $step = 1) { for ($i = $start; $i = $limit; $i += $step) { yield $i;}

讓我們將它與無迭代器支持的數組進行比較:

foreach xrange($start, $limit, $step = 1) { $elements = []; for ($i = $start; $i = $limit; $i += $step) { $elements[] = $i; return $elements;}

這兩個版本的函數都支持 foreach 迭代獲取所有元素:

foreach (xrange(1, 100) as $i) { print $i . PHP_EOL;}

所以除了一個更短的函數定義,我們還能獲取什么呢?yield 到底做了什么?為什么在第一個函數定義時依然可以返回數據,即使沒有 return 語句?

先從返回值說起。生成器是 PHP 中的一個很特別的函數。當一個函數包含 yield,那么這個函數即不再是一個普通函數,它永遠返回一個「Generator(生成器)」實例。生成器實現了 Iterator 接口,這就是為何它能夠進行 foreach 遍歷的原因。

接下來我使用 Iterator 接口中的方法,對之前的 foreach 循環進行重寫。你可以在 3v4l.org 查看結果。

$generator = xrange(1, 100);while($generator- valid()) { print $generator- html' target='_blank'>current() . PHP_EOL; $generator- next();}

我們可以清楚的看到生成器是更高級的技術,現在讓我們編寫一個新的生成器示例來更好的理解到底在生成器內部是如何進行處理的吧。

function foobar() { print foobar - start . PHP_EOL; for ($i = 0; $i $i++) { print foobar - yielding... . PHP_EOL; yield $i; print foobar - continued... . PHP_EOL; print foobar - end . PHP_EOL;$generator = foobar();print Generator created . PHP_EOL;while ($generator- valid()) { print Getting current value from the generator... . PHP_EOL; print $generator- current() . PHP_EOL; $generator- next();}
Generator createdfoobar - startfoobar - yielding...Getting current value from the generator...foobar - continuedfoobar - yielding...Getting current value from the generator...foobar - continuedfoobar - yielding...Getting current value from the generator...foobar - continuedfoobar - yielding...Getting current value from the generator...foobar - continuedfoobar - yielding...Getting current value from the generator...foobar - continuedfoobar - end

嗯?為什么 Generator created 最先打印出來?這是因為生成器在被使用之前不會執行任何操作。在上例中就是$generator- valid()** 這句代碼才開始執行生成器。我們看到生成器一直運行到了第一個 **yield** 時,將控制流程交還給調用者 **$generator- valid()。$generator- next() 調用時則恢復生成器執行,到下一個 yield 再次停止運行,如此反復直到沒有更多的 yield 為止。我們現在擁有了可以在任何 yield 執行暫停和回復的終端函數。這個特性允許編寫客戶端所需的延遲函數。

你可以創建一個從 GitHub API 讀取所有用戶的功能。支持分頁處理,但是你可以隱藏這些細節并且僅當需要時再去獲取下一頁數據。你可以使用 yield 從當前頁面獲取每個用戶數據,直到當前頁所有用戶獲取完成,你就可以再去獲取下一頁數據。

class GitHubClient { function getUsers(): Iterator { $uri = /users  do { $response = $this- get($uri); foreach ($response- items as $user) { yield $user; $uri = $response- nextUri; } while($uri !== null);}

客戶端可以迭代出所有用戶或者在任何時候停止遍歷。

把生成器當迭代器使用真是無聊

是的,你的想法是對的。以上我給出的所有講解任何人都可以從 PHP 文檔中獲取到。但是作為迭代器這些使用,連它強大功能的一半都沒用到。生成器還提供了不屬于 Iterator 接口的 send() 和 throw() 功能。我們前面談到了暫停和恢復生成器執行功能。當需要恢復生成器時,不僅可以功過 Generator::next() 方法,還可以使用 Generator::send() 和 Generator::throw()方法。

Generator::send() 允許你指定 yield 的返回值,而 Generator::throw() 允許向 yield 拋出異常。通過這些方法我們不僅可以從生成器中獲取數據,還能向生成器中發送新數據。

讓我們看一個從 Cooperative multitasking using coroutines(強烈推薦閱讀本文)摘取的 Logger 日志示例。

function logger($filename) { $fileHandle = fopen($filename, a  while (true) { fwrite($fileHandle, yield . /n $logger = logger(__DIR__ . /log $logger- send( Foo $logger- send( Bar 

yield 在這里是作為表達式使用的。當我們發送數據時,從 yield 返回數據然后作為參數傳入到 fwrite()。

講真,這個示例在實際項目中沒毛用。它僅僅用于演示 Generator::send() 的使用原理,但是僅僅能夠發送數據并沒有太大作用。如果有一個類和普通函數支持的話就不一樣了。

使用生成器的樂趣來自于通過 yield 創建數據,然后由「生成器執行程序(generator runner)」依據這個數據來處理業務,然后再繼續執行生成器。這就是「協程(coroutines)」和「狀態流解析器(stateful streaming parsers)」實例。在講解協程和狀態流解析器之前,我們快速瀏覽一下如何在生成器中返回數據,我們還沒有將接觸這方面的知識。從 PHP 5.5 開始我們可以在生成器內部使用 return; 語句,但是不能返回任何值。執行 return; 語句的唯一目的是結束生成器執行。

不過從 PHP 7.0 起支持返回值。這個功能在用于迭代時可能有些奇怪,但是在其他使用場景如協程時將非常有用,例如,當我們在執行一個生成器時我們可以依據返回值處理,而無需直接對生成器進行操作。下一節我們將講解 return 語句在協程中的使用。

異步生成器

Amp 是一款 PHP 異步編程的框架。支持異步協程功能,本質上是等待處理結果的占位符?!干善鲌绦谐绦颉篂?Coroutine類。它會訂閱異步生成器(yielded promise),當有執行結果可用時則繼續生成器處理。如果處理失敗,則會拋出異常給生成器。你可以到 amphp/amp 版本庫查看實現細節。在 Amp 中的 Coroutine 本身就是一個 Promise。如果這個協程拋出未經捕獲的異常,這個協程就執行失敗了。如果解析成功,那么就返回一個值。這個值看起來和普通函數的返回值并無二致,只不過它處于異步執行環境中。這就是需要生成器需要有返回值的意義,這也是為何我們將這個特性加入到 PHP 7.0 中的原因,我們會將最后執行的yield 值作為返回值,但這不是一個好的解決方案。

Amp 可以像編寫阻塞代碼一樣編寫非阻塞代碼,同時允許在同一進程中執行其它非阻塞事件。一個使用場景是,同時對一個或多個第三方 API 并行的創建多個 HTTP 請求,但不限于此。得益于事件循環,可以同時處理多個 I/O 處理,而不僅僅是只能處理多個 HTTP請求這類操作。

Loop::run(function() { $uris = [ http://google.com/ , http://github.com/ , http://stackoverflow.com/ , $client = new Amp/Artax/DefaultClient; $promises = []; foreach ($uris as $uri) { $promises[$uri] = $client- request($uri); $responses = yield $promises; foreach ($responses as $uri = $response) { print $uri . - . $response- getStatus() . PHP_EOL;});

但是,擁有異步功能的協程并非只能夠在 yield 右側出現變量,還可以在它的左側。這就是我們前面提到的解析器。

$parse = new Parser((function(){ while (true) { $line = yield /r/n  if (trim($line) === ) { continue; print New item: {$line} . PHP_EOL;})());for ($i = 0; $i 100; $i++) { $parser- push( bar/r  $parser- push( /nfoo }

解析器會緩存所有輸入直到接收的是 rn。這類生成器解析器并不能簡化簡單協議處理(如換行分隔符協議),但是對于復雜的解析器,如在服務器解析 HTTP 請求的 Aerys。

相關推薦:

如何利用PHP實現開發中基于layUI的三級聯動效果的代碼

關于IIS下PHP快三平臺源碼的架設環境的配置過程

以上就是淺談一下PHP生成器的使用方法的詳細內容,PHP教程

鄭重聲明:本文版權歸原作者所有,轉載文章僅為傳播更多信息之目的,如作者信息標記有誤,請第一時間聯系我們修改或刪除,多謝。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲乱码国产乱码精品精天堂| 中文字幕欧美精品日韩中文字幕| 亚洲精品国产精品乱码不99按摩| 成人妇女免费播放久久久| 日韩av网站导航| 中文字幕日韩精品在线观看| 日本高清视频一区| 色噜噜亚洲精品中文字幕| 国产美女扒开尿口久久久| 久久久久国产一区二区三区| 欧美视频第一页| 亚洲国产成人精品女人久久久| 98视频在线噜噜噜国产| 亚洲精品国产拍免费91在线| 国产精品亚洲综合天堂夜夜| 国产一区二区在线播放| 亚洲男人天堂古典| 欧美精品在线免费播放| 亚洲免费一在线| 高清日韩电视剧大全免费播放在线观看| 久久国产精品久久久久久| 色噜噜国产精品视频一区二区| 色播久久人人爽人人爽人人片视av| 日韩精品视频在线免费观看| 91在线视频成人| 亚洲色图13p| 91av在线视频观看| 日韩在线激情视频| 欧美裸体男粗大视频在线观看| 91精品综合视频| 日韩欧美成人精品| 亚洲精品久久久久久久久久久久久| 国色天香2019中文字幕在线观看| 色在人av网站天堂精品| 欧美性极品xxxx做受| 国产这里只有精品| 亚洲国产精品小视频| 久久久久久久一区二区| 久久精品免费电影| 亚洲二区在线播放视频| 亚洲欧洲美洲在线综合| 国产精品视频自在线| 在线观看国产成人av片| 欧美成人免费在线观看| 欧美黑人巨大xxx极品| 国产欧美一区二区| 日本人成精品视频在线| 一级做a爰片久久毛片美女图片| 国产xxx69麻豆国语对白| 国产成人一区二区三区| 国产98色在线| 91色中文字幕| 日韩h在线观看| 中文字幕精品在线视频| 亚洲视频999| 91精品国产91久久久久久| 国产精品久久久久久久av电影| 亚洲欧美日韩国产成人| 欧美黑人又粗大| 色偷偷888欧美精品久久久| 亚洲偷熟乱区亚洲香蕉av| 久久精品国产综合| 5566成人精品视频免费| 国产亚洲精品一区二555| 精品久久久久久久大神国产| 国产精品高清免费在线观看| 欧美午夜视频在线观看| 成人天堂噜噜噜| 国产精品一区二区在线| 97精品国产97久久久久久| 久久综合国产精品台湾中文娱乐网| 欧美国产中文字幕| 亚洲性69xxxbbb| 亚洲热线99精品视频| 欧美亚洲激情在线| 精品亚洲一区二区三区在线观看| 亚洲精品国产电影| 国产成人亚洲综合青青| 国产精品久久中文| 欧美在线一区二区三区四| 狠狠久久五月精品中文字幕| 国产精品影片在线观看| 91网站在线看| 精品视频久久久久久| 91色视频在线观看| 国产ts人妖一区二区三区| 国产69精品99久久久久久宅男| 欧美体内谢she精2性欧美| 欧美亚洲另类激情另类| 欧美中文在线免费| 久久99久久99精品中文字幕| 午夜精品美女自拍福到在线| 国产精品无码专区在线观看| 中文字幕欧美专区| 国产99视频精品免视看7| 亚洲免费伊人电影在线观看av| 成人性生交大片免费看视频直播| 日本国产欧美一区二区三区| 91影院在线免费观看视频| 91精品国产成人| 亚洲已满18点击进入在线看片| 中文日韩在线视频| 国产z一区二区三区| 国产欧美日韩专区发布| 国产精品嫩草影院一区二区| 久久久精品国产一区二区| 亚洲国产精品va在线| 在线观看欧美日韩国产| 欧美日韩国产综合视频在线观看中文| 精品国产91久久久久久老师| 热久久视久久精品18亚洲精品| 奇米四色中文综合久久| 亚洲美女av在线| 尤物tv国产一区| 亚洲精品国产拍免费91在线| 国产亚洲美女精品久久久| 国产va免费精品高清在线| 久久久噜噜噜久噜久久| 欧美成人在线免费视频| 欧美国产精品日韩| 日韩精品极品在线观看| 精品香蕉在线观看视频一| 亚洲伊人第一页| 91精品在线国产| 亚洲国产欧美一区二区三区久久| 一区二区av在线| 欧美最顶级的aⅴ艳星| 国产亚洲精品美女| 国产成人av在线播放| 97在线观看免费高清| 久久久久久18| 欧美丝袜一区二区三区| 5252色成人免费视频| 久久久久久高潮国产精品视| 日韩av影片在线观看| 久久99青青精品免费观看| 亚洲精品97久久| 青青精品视频播放| 欧美激情按摩在线| 国产精品亚洲激情| 国产精品一区二区三区久久久| 成人激情黄色网| 亚洲视频第一页| 欧美日韩亚洲精品一区二区三区| 美日韩丰满少妇在线观看| 久久成人国产精品| xxx成人少妇69| 日本不卡免费高清视频| 欧美成人精品一区二区三区| 久热在线中文字幕色999舞| 97成人精品区在线播放| 亚洲人成在线一二| 91精品免费久久久久久久久| 国产精品久久久久影院日本| 美女av一区二区| 国产亚洲精品一区二区| 色一情一乱一区二区| 国产日韩欧美夫妻视频在线观看| 51久久精品夜色国产麻豆| 欧美在线视频免费| 欧美成人免费观看| 亚洲欧美一区二区三区久久| 亚洲精品一区二区久| www.欧美免费|