PHP.mk документација

Преглед на генератори

Почист и полокален преглед на PHP референцата, со задржана структура од PHP.net и подобра читливост за примери, секции и белешки.

language.generators.overview.php PHP.net прокси Преводот е вчитан
Оригинал на PHP.net
Патека language.generators.overview.php Локална патека за оваа страница.
Извор php.net/manual/en Оригиналниот HTML се реупотребува и локално се стилизира.
Режим Прокси + преведен приказ Кодовите, табелите и белешките остануваат читливи во истиот тек.
Преглед на генератори

Референца за `language.generators.overview.php` со подобрена типографија и навигација.

language.generators.overview.php

Преглед на генератори

Распакување на вгнездени низи

(PHP 5 >= 5.5.0, PHP 7, PHP 8) iterators Генераторите обезбедуваат лесен начин за имплементирање едноставни Итератор interface.

без overhead или сложеноста на имплементирање класа што имплементира foreach Генераторот нуди удобен начин за обезбедување податоци до functionциклуси без потреба да се изгради низа во меморијата однапред, што може да предизвика програмата да го надмине лимитот на меморијата или да бара значително време за обработка за генерирање. Наместо тоа, може да се користи генераторска функција, која е иста како нормална return, освен што наместо yield еднаш, генератор може

колку пати што е потребно за да ги обезбеди вредностите што треба да се итерираат. Како и со итераторите, случајниот пристап до податоци не е возможен. range() Едноставен пример за ова е повторно имплементирање на range() функцијата како генератор. Стандардната функција мора да генерира низа со секоја вредност во неа и да ја врати, што може да резултира со големи низи: на пример, повикување range(0, 1000000)

ќе резултира со над 100 MB искористена меморија. xrange() Како алтернатива, можеме да имплементираме Итератор генератор, кој ќе бара само доволно меморија за создавање

објект и следење на тековната состојба на генераторот внатрешно, што изнесува помалку од 1 килобајт. range() Пример #1 Имплементирање

<?php
function xrange($start, $limit, $step = 1) {
if (
$start <= $limit) {
if (
$step <= 0) {
throw new
LogicException('Step must be positive');
}

for (
$i = $start; $i <= $limit; $i += $step) {
yield
$i;
}
} else {
if (
$step >= 0) {
throw new
LogicException('Step must be negative');
}

for (
$i = $start; $i >= $limit; $i += $step) {
yield
$i;
}
}
}

/*
* Note that both range() and xrange() result in the same
* output below.
*/

echo 'Single digit odd numbers from range(): ';
foreach (
range(1, 9, 2) as $number) {
echo
"$number ";
}
echo
"\n";

echo
'Single digit odd numbers from xrange(): ';
foreach (
xrange(1, 9, 2) as $number) {
echo
"$number ";
}
?>

Пример #1 Пример што покажува затворачка ознака што го опфаќа последниот нов ред

Single digit odd numbers from range():  1 3 5 7 9
Single digit odd numbers from xrange(): 1 3 5 7 9

за собирање на сите вредности додека ги игнорира клучевите вратени од objects

како генератор за собирање на сите вредности додека ги игнорира клучевите вратени од Кога се повикува генераторска функција, се враќа нов објект од внатрешната Итератор интерфејс на многу сличен начин како што би направил итератор објект само напред, и обезбедува методи што можат да се повикаат за манипулирање на состојбата на генераторот, вклучително и испраќање вредности до него и враќање вредности од него.

Белешки од корисници 6 белешки

bloodjazman на gmail точка com
12 години пред
for the protection from the leaking of resources 
see RFC https://wiki.php.net/rfc/generators#closing_a_generator

and use finnaly

sample code

function getLines($file) {
    $f = fopen($file, 'r');
    try {
        while ($line = fgets($f)) {
            yield $line;
        }
    } finally {
        fclose($f);
    }
}

foreach (getLines("file.txt") as $n => $line) {
    if ($n > 5) break;
    echo $line;
}
montoriusz на gmail точка com
пред 9 години
Bear in mind that execution of a generator function is postponed until iteration over its result (the Generator object) begins. This might confuse one if the result of a generator is assigned to a variable instead of immediate iteration.

<?php

$some_state = 'initial';

function gen() {
    global $some_state; 

    echo "gen() execution start\n";
    $some_state = "changed";

    yield 1;
    yield 2;
}

function peek_state() {
    global $some_state;
    echo "\$some_state = $some_state\n";
}

echo "calling gen()...\n";
$result = gen();
echo "gen() was called\n";

peek_state();

echo "iterating...\n";
foreach ($result as $val) {
    echo "iteration: $val\n";
    peek_state();
}

?>

If you need to perform some action when the function is called and before the result is used, you'll have to wrap your generator in another function.

<?php
/**
  * @return Generator
  */
function some_generator() {
    global $some_state;

    $some_state = "changed";
    return gen();
}
?>
chung1905 на gmail точка com
пред 6 години
In addition to the note of "montoriusz at gmail dot com": https://www.php.net/manual/en/language.generators.overview.php#119275

"If you need to perform some action when the function is called and before the result is used, you'll have to wrap your generator in another function."
You can use Generator::rewind instead (https://www.php.net/manual/en/generator.rewind.php)

Sample code:
<?php
/** function/generator definition **/

echo "calling gen()...\n";
$result = gen();
$result->rewind();
echo "gen() was called\n";

/** iteration **/
?>
Адил Илхан (adilmedya at gmail dot com)
пред 10 години
Here's how to detect loop breaks, and how to handle or cleanup after an interruption.

<?php
    function generator()
    {
        $complete = false;
        try {

            while (($result = some_function())) {
                yield $result;
            }
            $complete = true;

        } finally {
            if (!$complete) {
                // cleanup when loop breaks 
            } else {
                // cleanup when loop completes
            }
        }

        // Do something only after loop completes
    }
?>
dc на libertyskull точка com
12 години пред
Same example, different results:

----------------------------------
           |  time  | memory, mb |
----------------------------------
| not gen  | 0.7589 | 146.75     |
|---------------------------------
| with gen | 0.7469 | 8.75       |
|---------------------------------

Time in results varying from 6.5 to 7.8 on both examples.
So no real drawbacks concerning processing speed.
lubaev
12 години пред
Abstract test.
<?php

$start_time=microtime(true);
$array = array();
$result = '';
for($count=1000000; $count--;)
{
  $array[]=$count/2;
}
foreach($array as $val)
{
  $val += 145.56;
  $result .= $val;
}
$end_time=microtime(true);

echo "time: ", bcsub($end_time, $start_time, 4), "\n";
echo "memory (byte): ", memory_get_peak_usage(true), "\n";

?>

<?php

$start_time=microtime(true);
$result = '';
function it()
{
  for($count=1000000; $count--;)
  {
    yield $count/2;
  }
}
foreach(it() as $val)
{
  $val += 145.56;
  $result .= $val;
}
$end_time=microtime(true);

echo "time: ", bcsub($end_time, $start_time, 4), "\n";
echo "memory (byte): ", memory_get_peak_usage(true), "\n";

?>
Result:
----------------------------------
           |  time  | memory, mb |
----------------------------------
| not gen  | 2.1216 | 89.25      |
|---------------------------------
| with gen | 6.1963 | 8.75       |
|---------------------------------
| diff     | < 192% | > 90%      |
----------------------------------
На оваа страница

Автоматски outline од активната документација.

Насловите ќе се појават тука по вчитување.

Попрегледно читање

Примерите, changelog табелите и user notes се визуелно издвоени за да не се губат во долгата содржина.

Брз совет Користи го outline-от Скокни директно на главните секции од активната страница.
Извор Оригиналниот линк останува достапен Кога ти треба целосен upstream context, отвори го PHP.net во нов tab.