Генераторы на PHP |
Время от времени мы сталкиваемся с проблемами, когда приложения PHP потребляют довольно много памяти и неэффективно используют память из-за того, как мы пишем наши приложения, или когда мы не используем некоторые функции, предоставляемые самим PHP, которые помогают управлять памятью. . Примером функции, которую можно использовать в качестве преимущества для сокращения использования памяти, являются генераторы. Ты сказал Что? Да — Генераторы! Итак, углубляемся…
Что такое Генераторы?
Генераторы — это в основном функции, которые возвращают множество значений, которые можно повторять. В отличие от перебора массива, вы можете контролировать процесс перебора значений, возвращаемых генератором. Другими словами, мы можем контролировать итерацию значений и делать такие вещи, как возврат значений, когда мы хотим или столько, сколько мы хотим, или приостанавливать итерацию, или даже перематывать итерацию и переводить ее на другой уровень, мы можем отправлять значения обратно через генераторы.
В отличие от обычной функции, которая напрямую returns
что-то генератор yields
что-то, хотя PHP 7 теперь поддерживает функции, выдающие значения, а также возвращающие значения, но такая функция по-прежнему считается генератором. Когда yield
появляется в теле функции, PHP распознает такую функцию как Генератор.
Помещение объяснения в код
У нас есть наша нормальная функция с return
как это:
<?php
function foo($a, $b) { return $a + $b; }
Но такая функция, как приведенная ниже, считается не функцией, а генератором:
<?php
function bar($a, $b) { yield $a + $b; }
Чтобы доказать это, я буду использовать этот код:
<?php
function foo($a, $b) {
return $a + $b;
}
function bar($a, $b) {
yield $a + $b;
}
var_dump(foo(2, 3));
echo PHP_EOL;
var_dump(bar(2, 3));
Когда я запускаю это, я получил такой результат:
int(5) class Generator#1 (0) {
}
Вызов функции foo(2, 3)
возвращается int(5)
как и ожидалось, но вызов функции bar(2, 3)
возвращает экземплярGenerator
учебный класс. Ясно видно, что единственная разница в теле функции — это yield
ключевое слово, используемое вместо return
ключевое слово. Итак, подводя итог, каждый раз, когда вы используете yield
ключевое слово в функции, PHP автоматически воспринимает его как Generator
и он возвращает объект Generator.
Но как нам получить доступ к значению генератора?
Класс генератора реализует IteratorInterface
который предоставляет несколько методов, которые можно использовать для доступа к значениям в Генераторе. Вы можете прочитать о IteratorInterface
здесь.
Чтобы доказать это, мы добавим это в наш исходный код:
<?php
function foo($a, $b) {
return $a + $b;
}
function bar($a, $b) {
yield $a + $b;
}
var_dump(foo(2, 3));
echo PHP_EOL;
var_dump(bar(2, 3));
echo PHP_EOL;
var_dump(bar(2, 3) instanceof Iterator);
И получаем результат ниже:
int(5) class Generator#1 (0) {
}
bool(true)
Мы получаем true
это означает, что класс Generator реализует интерфейс Iterator.
Получение результата
Теперь, если мы позвоним ->current()
метод на bar(2, 3)
вызов функции так:
<?php
echo PHP_EOL;
var_dump(bar(2, 3)->current());
Мы получим ожидаемое int(5)
как результат. Мы смогли воспользоваться ->current()
потому что класс Generator реализовал Iterator
интерфейс.
Как видно из документации Iterator здесьдругие методы, к которым можно получить доступ, next()
, previous()
, key()
а также valid()
, документация объясняет работу этих методов, а также их возвращаемые значения. Я рекомендую вам прочитать больше об этом.
Другой пример
В исходном примере мы yielded
только один результат, но генератор на самом деле позволяет получить много результатов, давайте посмотрим на пример:
<?php
function compute($x, $y) {
yield $x + $y;
yield $x * $y;
yield $x / $y;
yield $x - $y;
}
Приведенная выше функция вычисляет сложение, вычитание, умножение и деление двух чисел. Теперь давайте получим результат, добавив это в наш код:
<?php
$computation = compute(2, 3);
$addition = $computation->current();
echo "Addition: $addition" . PHP_EOL;
$computation->next();
$multiplication = $computation->current();
echo "Multiplication: $multiplication" . PHP_EOL;
$computation->next();
$division = $computation->current();
echo "Division: $division" . PHP_EOL;
$computation->next();
$subtraction = $computation->current();
echo "Subtraction: $subtraction" . PHP_EOL;
Эта инфраструктура — это то, что обеспечивает гибкость и мощность генераторов, которые можно использовать во многих случаях, что помогает программе, которую мы пишем, во многих отношениях, таких как скорость, управление памятью, потоковая передача и т. д.
В этой статье мы только рассмотрим, что такое генераторы и как мы можем их использовать, в следующих статьях я покажу, как генераторы могут помочь в экономии памяти, а в последующих статьях я объясню, как их можно использовать для улучшить скорость, а также другие приложения.
Вы можете прочитать больше о синтаксисе генератора здесь.