You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用生成器懒加载列表并持久化完整列表的实现疑问

解决方案

你遇到的核心问题是生成器属性无法直接返回列表,且原代码存在重复加载、迭代后无法直接获取完整列表的问题。以下是修正后的代码,完全满足你的需求:

import requests

class Phone:
    def __init__(self, id, name, type):
        self.id = id
        self.name = name
        self.type = type

    def __str__(self):
        return self.name

class A:
    def __init__(self):
        self._phones_cucm = []
        self._phone_map = {}  # 存储已加载的设备,避免重复请求
        self._all_loaded = False  # 标记是否已加载全部设备

    def _gen_phones(self):
        for phone_id in self._phones_cucm:
            if phone_id not in self._phone_map:
                # 仅当未加载时才发起请求
                resp = requests.get(f"https://example.com/phone/{phone_id}").json()
                self._phone_map[phone_id] = Phone(resp["id"], resp["name"], resp["type"])
            yield self._phone_map[phone_id]
        # 迭代完成后标记所有设备已加载
        self._all_loaded = True

    def get_phones(self, filter_type):
        self._phones_cucm = requests.get(
            f"https://example.com/phones?type={filter_type}"
        ).json()
        # 重置加载状态,避免旧数据干扰
        self._phone_map.clear()
        self._all_loaded = False

    @property
    def phones(self):
        if self._all_loaded:
            # 已加载全部数据,直接返回完整列表
            return list(self._phone_map.values())
        # 未加载完成时返回生成器,支持懒加载迭代
        return self._gen_phones()

def main():
    obj = A()
    obj.get_phones("desk_phone")
    
    # 迭代时懒加载每个设备的数据
    for phone in obj.phones:
        print(phone)
    
    # 迭代完成后,直接获取完整列表
    print(obj.phones)  # 输出所有Phone对象的列表

if __name__ == "__main__":
    main()

关键修改说明

  1. 避免重复加载:用_phone_map字典存储已加载的Phone对象,以设备ID为键,确保同一个设备不会重复发起请求。
  2. 加载状态标记:新增_all_loaded标志位,当生成器迭代完成(所有设备加载完毕)时标记为True。
  3. 动态返回类型:phones属性根据加载状态动态返回:
    • 未加载完成时返回生成器,实现迭代时逐个懒加载;
    • 加载完成后直接返回完整的设备列表,满足你迭代后直接调用完整列表的需求。
  4. 重置状态:调用get_phones时清空旧数据并重置加载状态,确保新的筛选条件能正确加载新数据。

原代码问题分析

  • 生成器属性的误区:原代码中phones属性用yield from返回生成器,导致每次访问obj.phones都会创建新的生成器对象,而非列表,这就是最后打印生成器而非列表的原因。
  • 生成器return的无效性:生成器中的return self._phones无法直接返回值,生成器的return值只会被封装在StopIteration异常的value属性中,无法通过常规迭代获取。
  • 重复添加数据:原代码每次迭代生成器都会将Phone对象追加到_phones列表,多次迭代会导致列表中出现重复对象。

内容的提问来源于stack exchange,提问作者Xemrer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 15:39:23