zoukankan      html  css  js  c++  java
  • PHP 生成器Generators的入门理解和学习

    什么是生成器Generators

    生成器允许你在 foreach 代码块中写代码来迭代一组数据而不需要在内存中创建一个数组, 那会使你的内存达到上限,或者会占据可观的处理时间。相反,你可以写一个生成器函数,就像一个普通的自定义函数一样, 和普通函数只返回一次不同的是, 生成器可以根据需要 yield 多次,以便生成需要迭代的值。

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

    例子代码

    <?php
    /**
     * Created by PhpStorm.
     * User: chenbotome@163.com
     * Date: 2018/7/30
     * Time: 上午11:29
     */
    $start = xdebug_memory_usage();
    $num = 10000;
    function rangeWithGenerators($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;
            }
        }
    }
    if ($argc === 1) {
        $iterate = rangeWithGenerators(0, $num, 1);
        foreach ($iterate as $value){
            echo $value . "
    ";
        }
        //var_dump(iterator_to_array($iterate));
    }
    if ($argc === 2) {
        $test = range(0, $num, 1);
        foreach ($test as $value) {
            echo $value . "
    ";
        }
    }
    $end = xdebug_memory_usage();
    
    echo sprintf("内存消耗量%s
    ", convert($end-$start));
    
    function convert($size){
        $unit=array('b','kb','mb','gb','tb','pb');
        return @round($size/pow(1024,($i=floor(log($size,1024)))),2).' '.$unit[$i];
    }
    

    环境

    • PHP7.1
    • Xdebug

    执行命令

    • php test.php 结果返回:内存消耗量416 b
    • php test.php range 结果返回:内存消耗量4 mb

    测试结果论述

    • 通过代码的执行,比较除了PHP标准函数rang()和自定义函数rangeWithGenerators()之间的异同。实现了同样的目的,却消耗着不同的内存,生成器的优点显而易见。
    • rangeWithGenerators()使用了生成器,而生成器的关键就是使用yield关键词,yield常见的使用涉及到foreach和for两个流程控制语句。rangeWithGenerators()中for循环yield变量$i(yield可理解为生成-值,如同return可理解为返回-值)。
    • rangeWithGenerators()函数返回的便是一个生成器Generators( 使用var_dump($iterate)查看其类型 )。
    • 既然rangeWithGenerators()函数返回的是一个生成器,我们可以使用以下两种方式来使用:
    1. foreach循环该Generators,本例子中则使用该方法读取Generators。
    2. PHP标准函数iterator_to_array(),该函数将Generators转换为一个Array。

    使用场景,可查阅参考资料2

    参考资料:

    http://php.net/manual/zh/lang...
    实际生产中的使用

    原文地址:https://segmentfault.com/a/1190000015879089

  • 相关阅读:
    面向对象设计原则之接口隔离原则
    面向对象设计原则之开闭原则
    [OOD]违反里氏替换原则的解决方案
    错误程序
    error: ‘for’ loop initial declarations are only allowed in C99 mode
    函数模板
    查找
    队列类模板
    栈类模板
    单链表的结点类模板
  • 原文地址:https://www.cnblogs.com/lalalagq/p/9975539.html
Copyright © 2011-2022 走看看