账号密码登录
微信安全登录
微信扫描二维码登录

登录后绑定QQ、微信即可实现信息互通

手机验证码登录
找回密码返回
邮箱找回手机找回
注册账号返回
其他登录方式
分享
  • 收藏
    X
    关于yield使用的不解之处?
    36
    0

    场景是有四万条数据,需要更新某一个字段值,然后使用了yield,感觉使用和不使用的作用不大啊,是不是我用错了方法?

    第一种写法:

    init_data()里获取数据库数据,init()方法循环调用:

    /**
     * 这个方法用来获取数据库数据
     * 每次取2000条数据出来 存放在yield
     * 第一次默认取2000 之后会根据最大ID取2000条数据出来
     */
    public function init_data()
    {
        $search = array(
            'limit' => array(
                'persize' => 1000
            )
        );
        $max_id = 0;
        while(true) {
            if ($max_id === 0) {
                $result = $this->consum_record_model->get_values('id', 'consume_time', null, $search);
            } else if($max_id && $max_id > 0) {
                $attr = array('id_big' => $max_id);
                $result = $this->consum_record_model->get_values('id', 'consume_time', $attr, $search);
            } else {
                break;
            }
            // 对数组key值(id)排序 取出最大ID 
            krsort($result);
            $max_id = key($result);
    
            if (empty($result) && !is_array($result)) {
                break;
            } else {
                yield $result;
            }
        }
    }
    
    /**
     * 这里利用事务来对数据进行更新操作
     */
    public function init($id)
    {
        p(memory_get_usage());
        foreach ($this->init_data() as $value) {
            $this->db->trans_begin();
            foreach ($value as $id => $time) {
                $this->db->query("UPDATE consum_record SET time_type = ? WHERE id = ? ", array($this->get_time_type($time), $id));
            }
            if ($this->db->trans_status() === FALSE) {
                $this->db->trans_rollback();
            } else {
                $this->db->trans_commit();
            }
        }
        p(memory_get_usage());
        exit;
    }
    

    第二种写法:

    这种写法直接在while里面对数据库进行更新操作,只贴init_data()方法的while部分:

    while(true) {
        if ($max_id === 0) {
            $result = $this->consum_record_model->get_values('id', 'consume_time', null, $search);
        } else if($max_id && $max_id > 0) {
            $attr = array('id_big' => $max_id);
            $result = $this->consum_record_model->get_values('id', 'consume_time', $attr, $search);
        } else {
            break;
        }
        // 对数组key值(id)排序 取出最大ID 
        krsort($result);
        $max_id = key($result);
    
        if (empty($result) && !is_array($result)) {
            break;
        } else {
            $this->db->trans_begin();
            foreach ($result as $id => $time) {
                $this->db->query("UPDATE consum_record SET time_type = ? WHERE id = ? ", array($this->get_time_type($time), $id));
            }
            if ($this->db->trans_status() === FALSE) {
                $this->db->trans_rollback();
            } else {
                $this->db->trans_commit();
            }
            yield $result;
        }
    }

    然后我用memory_get_usage()函数来查看内存使用量,两种方法消耗的内存总量相差不多,开始是3M,结束时都在14M左右,平均执行时长在75s上下

    看了很多关于yield的概述,但是实际上对这个特性的应用场景并不是很理解,写的代码有问题,还请多多指教。

    0
    打赏
    收藏
    点击回答
        全部回答
    • 0
    • 深情不及久伴 普通会员 1楼

      yield是一个在Python语言中用于生成一个函数,该函数返回一个迭代器或生成器,以便从控制流中读取元素并继续执行。yield函数的常见用法包括:

      1. 生成器:yield语句用于创建一个生成器,它会在每次迭代时暂停并返回一个值,直到下一个yield语句被调用或结束函数。这使得生成器可以处理大量数据,使其更高效且易于处理。例如:

      python def square(x): while True: yield x ** 2

      在这个例子中,生成器会生成x的平方值,直到x的值大于0,然后它会返回x的平方值。使用while True的条件使生成器在每次迭代时暂停并返回x的平方值,直到x的值小于等于0。

      1. 函数式编程:在函数式编程中,yield语句是函数式编程的核心概念之一。函数式编程强调函数作为操作的对象,而不是单一的值。yield语句在函数式编程中通常用于返回一个值,然后在函数内部暂停执行,继续执行下一次调用。例如:

      python def multiply(x, y): while True: yield x * y

      在这个例子中,函数multiply返回x乘以y的结果,然后在函数内部暂停执行,等待下一次调用。在下一次调用multiply函数时,它会再次返回x乘以y的结果,这样就会一直循环下去,直到x和y的值都为0,然后函数将结束。

      1. 模块化:在模块化编程中,yield语句用于在函数内部暂停执行,并在需要时返回一个值。这样可以将函数分解为多个小型函数,使得代码更易于阅读和维护。例如:

      python def factorial(n): result = 1 while n > 0: result *= n n -= 1 return result

      在这个例子中,函数factorial返回n的阶乘,然后在函数内部暂停执行,等待n的值为0,然后将n的值乘以结果,然后返回结果。这样就将函数分解为一个返回阶乘的函数和一个暂停执行的函数,使得代码更易于阅读和维护。

      总的来说,yield语句在Python中主要用于生成函数,通过暂停和返回值的方式实现函数的迭代和操作。然而,它的使用并非孤立的,还可以配合其他函数和方法使用,以实现更复杂的功能。

    更多回答
    扫一扫访问手机版