yield 实现php
yield 在 PHP 中的实现
yield 是 PHP 5.5 引入的关键字,用于生成器(Generator)的实现。生成器提供了一种更简单的方式来创建迭代器,无需实现完整的 Iterator 接口。
生成器的基本语法
使用 yield 关键字可以定义一个生成器函数。生成器函数在调用时不会立即执行,而是返回一个 Generator 对象。每次调用 Generator 对象的 current() 或 next() 方法时,函数会执行到下一个 yield 语句处暂停。
function generatorFunction() {
yield 'value1';
yield 'value2';
yield 'value3';
}
$generator = generatorFunction();
foreach ($generator as $value) {
echo $value . "\n";
}
yield 的高级用法
yield 不仅可以返回值,还可以接收值。通过 Generator::send() 方法可以向生成器发送值,这个值会成为 yield 表达式的返回值。
function echoingGenerator() {
while (true) {
$value = yield;
echo $value . "\n";
}
}
$generator = echoingGenerator();
$generator->send('Hello');
$generator->send('World');
yield from 语法
PHP 7.0 引入了 yield from 语法,允许一个生成器委托给另一个生成器、迭代器或数组。
function generator1() {
yield 1;
yield 2;
}
function generator2() {
yield from generator1();
yield 3;
}
foreach (generator2() as $value) {
echo $value . "\n";
}
生成器的内存优势
生成器的主要优势在于内存效率。传统方法可能需要将整个数据集加载到内存中,而生成器可以一次只生成一个值,大大减少内存消耗。
function rangeGenerator($start, $end) {
for ($i = $start; $i <= $end; $i++) {
yield $i;
}
}
// 这会非常高效,即使范围很大
foreach (rangeGenerator(1, 1000000) as $number) {
// 处理每个数字
}
生成器与协程
生成器还可以用于实现简单的协程(coroutine),通过在生成器函数内部使用 yield 来暂停和恢复执行。
function task1() {
for ($i = 1; $i <= 3; $i++) {
echo "Task 1: $i\n";
yield;
}
}
function task2() {
for ($i = 1; $i <= 3; $i++) {
echo "Task 2: $i\n";
yield;
}
}
$t1 = task1();
$t2 = task2();
while ($t1->valid() || $t2->valid()) {
$t1->next();
$t2->next();
}
生成器的实际应用
生成器特别适合处理大型数据集、流式处理和实现简单的状态机。例如处理大型文件时,可以逐行读取而不需要将整个文件加载到内存中。

function readLargeFile($fileName) {
$file = fopen($fileName, 'r');
while (!feof($file)) {
yield fgets($file);
}
fclose($file);
}
foreach (readLargeFile('large_file.txt') as $line) {
// 处理每一行
}
注意事项
生成器只能向前迭代,一旦迭代完成就不能重新开始。生成器函数执行完毕后,不能再从中获取值。生成器对象实现了 Iterator 接口,因此可以使用 foreach 循环遍历。






