美文网首页
php yield生成器

php yield生成器

作者: yeedom | 来源:发表于2019-06-16 20:28 被阅读0次

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 +ve');
        }
        for ($i = $start; $i <= $limit; $i += $step) {
            yield $i;
        }
    } else {
        if ($step >= 0) {
            throw new LogicException('Step must be -ve');
        }
        for ($i = $start; $i >= $limit; $i += $step) {
            yield $i;
        }
    }
}

性能测试

使用下面这段代码测试,发现有几个现象:

一、当$num的值大到一定阀值时range方式会报fatal error

Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 134217736 bytes) in /Users/liuyidong/Documents/htdocs/hr.wiiqq.com/tmp/yield/test.php on line 6

二、yield方式会随着$num的值越大耗时越久,内存一直维持在0

<?php
$num = 700000;
$time_start = microtime_float();
$start = memory_get_usage();
echo 'range方式 : ';
foreach (range(1, $num, 2) as $number) {
    //    echo "$number ";
}
$memory = sprintf("%7.5f", memory_get_usage() - $start);
$time = sprintf("%7.5f", microtime_float() - $time_start);
echo "memory[{$memory}],time[{$time}]\n";

echo 'yield方式 : ';
$time_start = microtime_float();
$start = memory_get_usage();
foreach (xrange(1, $num, 2) as $number) {
    //    echo "$number ";
}
$memory = sprintf("%7.5f", memory_get_usage() - $start);
$time = sprintf("%7.5f", microtime_float() - $time_start);
echo "memory[{$memory}],time[{$time}]\n";

function microtime_float() {
    list($usec, $sec) = explode(" ", microtime());
    return ((float) $usec + (float) $sec);
}

语法

当一个生成器被调用的时候,它返回一个可以被遍历的对象.当你遍历这个对象的时候(例如通过一个foreach循环),PHP 将会在每次需要值的时候调用生成器函数,并在产生一个值之后保存生成器的状态,这样它就可以在需要产生下一个值的时候恢复调用状态。

一旦不再需要产生更多的值,生成器函数可以简单退出,而调用生成器的代码还可以继续执行,就像一个数组已经被遍历完了。

Note:
一个生成器不可以返回值: 这样做会产生一个编译错误。然而return空是一个有效的语法并且它将会终止生成器继续执行。

yield关键字

生成器函数的核心是yield关键字。它最简单的调用形式看起来像一个return申明,不同之处在于普通return会返回值并终止函数的执行,而yield会返回一个值给循环调用此生成器的代码并且只是暂停执行生成器函数。

简单例子

<?php
foreach (
    (function () {
        for ($i = 1; $i <= 3; $i ++) {
            //注意变量$i的值在不同的yield之间是保持传递的。
            yield $i;
        }
    })() as $value
) {
    echo "$value\n";
}

输出结果:

1
2
3

相关文章

  • PHP生成器和yield

    简介 生成器和yield结合可以实现php的协程 前置知识 如果对生成器和yield不了解,可以先看看下面两个博客...

  • PHP生成器yield

    生成器 生成器的语法 yield关键字 以上例程会输出:1-1000000 yield关键字,当开始调用的时候返回...

  • PHP生成器yield

    yield比较适合计算大量的数据,PHP代码运行时节省大量的内存。 官方实例(生成器读取大文件): functio...

  • php yield生成器

    yield生成器 介绍 一个简单的例子就是使用生成器来重新实现 range() 函数。 标准的 range() 函...

  • PHP中的yield 用途

    yield生成器是php5.5之后出现的,yield提供了一种更容易的方法来实现简单的迭代对象,相比较定义类实现 ...

  • Scrapy框架学习2

    yield关键字 yield<——>生成器 生成器是一个不断产生值的函数 包含yield语句 的函数是一个生...

  • 生成器(generator)

    调用生成器函数(yield)的时候,php会返回一个属于Generator类的对象.这个对象可以使用foreach...

  • python——yield

    使用了yield关键字的函数不再是函数,而是生成器。(使用了yield的函数就是生成器) yield关键字有两点作...

  • 协程

    从yield说起 当生成器执行到yield的时候,通过send方法向生成器传递一个值,生成器在收到传进来的值之后,...

  • yield

    yield 生成器, 当函数中有yield, 那么这个函数编程生成器, 对其进行函数调用, 不会执行, 会返回一个...

网友评论

      本文标题:php yield生成器

      本文链接:https://www.haomeiwen.com/subject/dnfnfctx.html