<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                生成器優點: * 生成器會對PHP應用的性能有非常大的影響 * PHP代碼運行時節省大量的內存 * 比較適合計算大量的數據 ## **[yield](https://www.php.net/manual/zh/language.generators.syntax.php#control-structures.yield)** 生成器函數的核心是**yield**關鍵字[yield](https://www.php.net/manual/zh/language.generators.syntax.php#control-structures.yield)的功能是讓程序自己交出控制權,并停留在當前的執行位置,yield看起來像一個return,不同之處在于普通return會返回值并終止函數的執行,而**yield會返回給一個值給循環調用此生成器的代碼**并且只是**暫停執行生成器**函數,同時也可以接收生成器傳遞過來的數據并替換當前yield表達式,可以看成是雙向管道 * (迭代)生成器也是一個函數,不同的是這個函數的返回值是依次返回(遍歷返回),而不是只返回一個單獨的值 * PHP5.5一個比較好的新功能是加入了對迭代生成器和協程的支持. * 生成器是一種可中斷的函數, 在它里面的yield構成了中斷點 >[info]生成器允許你在 foreach 代碼塊中寫代碼來迭代一組數據而不需要在內存中創建一個數組,那會使你的內存達到上限,或者會占據可觀的處理時間。相反,你可以寫一個生成器函數,就像一個普通的自定義函數一樣,和普通函數只返回一次不同的是,生成器可以根據需要 yield 多次,以便生成需要迭代的值。 > >* 一個簡單的例子就是使用生成器來重新實現 range () 函數。 標準的 range () 函數需要在內存中生成一個數組包含每一個在它范圍內的值,然后返回該數組,結果就是會產生多個很大的數組。 比如,調用 range (0, 1000000) 將導致內存占用超過 100 MB。 做為一種替代方法,我們可以實現一個 xrange () 生成器,只需要足夠的內存來創建 Iterator 對象并在內部跟蹤生成器的當前狀態,這樣只需要不到 1K 字節的內存。 >* 當一個生成器被調用的時候,它返回一個可以被遍歷的對象。當你遍歷這個對象的時候 (例如通過一個 foreach 循環),PHP 將會在每次需要值的時候調用生成器函數,并在產生一個值之后保存生成器的狀態,這樣它就可以在需要產生下一個值的時候恢復調用狀態。 一旦不再需要產生更多的值,生成器函數可以簡單退出,而調用生成器的代碼還可以繼續執行,就像一個數組已經被遍歷完了。 ``` <?php function xrange($start, $end, $step = 1) { for ($i = $start; $i <= $end; $i += $step) { yield $i; //自動生成數字索引鍵 //指定鍵名 //$id=$i-1; //yield?$id?=>?$i; //生成null值 //yield;//自動生成數字索引鍵 } } //調用xrange(1,1000000)的時候, xrange()函數里代碼其實并沒有真正地運行. 它只是返回了一個迭代器 $range = xrange(1, 1000000); var_dump($range); // object(Generator)#1 var_dump($range instanceof Iterator); // bool(true) //這也解釋了為什么xrange叫做迭代生成器, 因為它返回一個迭代器, 而這個迭代器實現了Iterator接口. /* 調用迭代器的方法一次, 其中的代碼運行一次.例如, 如果你調用$range->rewind(), 那么xrange()里的代碼就會運行到控制流第一次出現yield的地方. 而函數內傳遞給yield語句的返回值可以通過$range->current()獲取. 為了繼續執行生成器中yield后的代碼, 你就需要調用$range->next()方法. 這將再次啟動生成器, 直到下一次yield語句出現. 因此,連續調用next()和current()方法, 你就能從生成器里獲得所有的值, 直到再沒有yield語句出現. 對xrange()來說, 這種情形出現在$i超過$end時. 在這中情況下, 控制流將到達函數的終點,因此將不執行任何代碼.一旦這種情況發生,vaild()方法將返回假, 這時迭代結束. */ ?> ``` #### 使用引用來生成值 ``` <?php function &gen_reference() { $value = 3; while ($value > 0) { yield $value; } } /* * 我們可以在循環中修改$number的值,而生成器是使用的引用值來生成,所以gen_reference()內部的$value值也會跟著變化。 */ foreach (gen_reference() as &$number) { echo (--$number).'... '; } ?> ``` ~~~ 輸出: 2... 1... 0... ~~~ ### 通過yield from實現生成器委派 在PHP 7中,生成器委派允許您通過使用yield from keyword來從另一個生成器,Traversable對象或數組中生成值。然后外部生成器將從內部生成器,對象或數組中生成所有值,直到它不再有效,之后將在外部生成器中繼續執行。如果生成器與yield from一起使用,則expression的yield也將返回內部生成器返回的任何值。 ``` <?php function count_to_ten() { yield 1; yield 2; yield from [3, 4]; yield from new ArrayIterator([5, 6]); yield from seven_eight(); yield 9; yield 10; } function seven_eight() { yield 7; yield from eight(); } function eight() { yield 8; } foreach (count_to_ten() as $num) { echo "$num "; } ?> ``` ``` 以上例程會輸出: 1 2 3 4 5 6 7 8 9 10 ``` # **協程:** ## [在PHP中使用協程實現多任務調度](http://www.laruence.com/2015/05/28/3038.html) >正如你能看到,這兒yield沒有作為一個語句來使用, 而是用作一個表達式, 即它能被演化成一個值. 這個值就是調用者傳遞給send()方法的值. 如下例子里, yield表達式將首先被”Foo”替代寫入Log, 然后被”Bar”替代寫入Log. ``` <?php function logger($fileName) { $fileHandle = fopen($fileName, 'a'); while (true) { fwrite($fileHandle, yield . "\n"); } } $logger = logger(__DIR__ . '/log'); $logger->send('Foo'); $logger->send('Bar'); //生成的log文件內容許下: /* Foo Bar */ ``` >[info]上面的例子里演示了yield作為接受者, 接下來我們看如何同時進行接收和發送的例子: ~~~ <?php function gen() { $ret = (yield 'yield1'); var_dump($ret);echo "|y1|<br>"; $ret = (yield 'yield2'); var_dump($ret);//ret2 } $gen = gen(); var_dump($gen->current()); //yield1 初始指針停留在 $ret = (yield 'yield1');位置 echo 111;var_dump($gen->send('ret1'));echo 2222; //yield2 (第一次var_dump send改變了指針停留位置的值且隱式的調用了next指針移動到$ret = (yield 'yield2');) var_dump($gen->current()); //yield2 var_dump($gen->send('ret2')); //null ?> ~~~ ## **多任務協作** 多任務協作這個術語中的“協作”說明了如何進行這種切換的:它要求當前正在運行的任務自動把控制傳回給調度器,這樣它就可以運行其他任務了。這與“搶占”多任務相反,搶占多任務是這樣的:調度器可以中斷運行了一段時間的任務,不管它喜歡還是不喜歡。協作多任務在Windows的早期版本(windows95)和Mac OS中有使用,不過它們后來都切換到使用搶先多任務了。理由相當明確:如果你依靠程序自動傳回 控制的話,那么壞行為的軟件將很容易為自身占用整個CPU,不與其他任務共享。? 這個時候你應當明白協程和任務調度之間的聯系:yield指令提供了任務中斷自身的一種方法,然后把控制傳遞給調度器。因此協程可以運行多個其他任務。更進一步來說,yield可以用來在任務和調度器之間進行通信。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看