5.2PHP语言的生成器(Generator)

生成器提供了一种更容易的方法来实现简单的对象迭代。

相比较定义类实现 Iterator 接口的方式,相同的是调用生成器函数时会返回一个内部的 Generator 类的对象,该 Generator 类实现了 Iterator 接口。不同的是,生成器性能更优异,代码更简洁。

性能更优异

生成器使用了“懒”执行,一次只有一个值会被创建并保存在内存中而不需要在内存中创建一个数组, 那会使你的内存达到上限,或者会占据可观的处理时间。该特性在面对无法载入到内存的大型数据集时非常有用。

代码更简洁

生成器函数定义时,就像一个普通的自定义函数一样。

与普通函数不同的是:普通函数使用 return 关键字返回一个值并终止函数的执行, 而 yield 关键字会返回一个值给循环调用此生成器的代码并且只是暂停执行生成器,最终生成器可以 yield 生成多个想要的值。

yield

一个简单的例子就是使用生成器来重新实现 range() 函数。 标准的 range() 函数需要在内存中生成一个数组包含每一个在它范围内的值,然后返回该数组, 结果就是会产生多个很大的数组。 比如,调用 range(0, 1000000) 将导致内存占用超过 100 MB。

做为一种替代方法, 我们可以实现一个 xrange() 生成器, 只需要足够的内存来创建 Iterator 对象并在内部跟踪生成器的当前状态,这样只需要不到1K字节的内存。

<?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;
        }
    }
}

/* 
 * 注意下面range()和xrange()输出的结果是一样的。
 */

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 ";
}
?>

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

yield from

yield from 表达式将返回内部生成器返回的任何值。

<?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 

原创文章,作者:huoxiaoqiang,如若转载,请注明出处:https://www.huoxiaoqiang.com/php/phplang/5326.html

(0)
上一篇 2021年5月2日 02:32
下一篇 2021年5月2日 21:44

相关推荐

  • 3.4PHP语言的Trait

    Trait与接口的最大区别是:Trait包含了实现,而接口则需要指定一个实现该接口的类。 Trait 和 Class 相似,但仅仅旨在用细粒度和一致的方式来组合功能。所以,Trait内部可定义抽象方法,静态属性,静态方法,实例属性,实例方法。 个人见解:Trait功能是接口的升级版,类似于Ruby语言中的Module(…

    PHP语言教程 2021年3月4日
    04230
  • 2.7PHP类(Class)类型之枚举(Enumeration)

    Enum 本质是一个类(Class),它的各种条目(case)是这个类的单例对象,又近似于可以理解为类常量。 1.纯粹(Pure)枚举 如果条目(case)没有关联数据,就称为“纯粹条目”(Pure Case)。 仅包含纯粹条目的枚举就称为“纯粹枚举“(Pure Enum)。 2.回退(Backed)枚举 由于有标量的…

    PHP语言教程 2021年2月7日
    02570
  • 3.3PHP语言的抽象(Abstract)类和接口(Interface)

    抽象类 PHP支持抽象类和抽象方法。定义为抽象的类不能被实例化但可以被子类继承。任何一个类,如果它里面至少有一个方法是被声明为抽象的,那么这个类就必须被声明为抽象的。被定义为抽象的方法只是声明了其调用方式(参数),不能定义其具体的功能实现。 继承一个抽象类的时候,子类必须定义父类中的所有抽象方法;另外,这些方法的访问控…

    PHP语言教程 2021年3月3日
    05550

发表评论

登录后才能评论