SDET / SWE · Technical Fundamentals

TikTok Python Generator:惰性执行、暂停与资源清理

解释yield创建和推进时机、单次消费与生成器内存,避免把惰性等同零存储。

题目重点:解释yield创建和推进时机、单次消费与生成器内存,避免把惰性等同零存储。

题意与假设

这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。

  • 训练普通同步生成器,不混入async generator;消费者可能提前停止。

解题路线

  1. 含yield的函数调用会创建生成器对象,函数体不是立即全部执行;next或迭代才推进到下一yield并返回值,同时保存局部变量和执行位置。
  2. 生成器是单次消费的迭代器,耗尽后再次list通常为空;需要重复遍历时重新调用生成器函数,不能无意缓存同一个已耗尽对象。
  3. 惰性适合大日志或分页处理,减少完整结果列表存储。但生成器局部变量、缓存、底层连接以及yield的对象仍占内存;若内部先read全文件再yield并未解决全量占用。
  4. 消费者提前退出时,资源生命周期不能寄希望于某解释器立即垃圾回收。用明确context manager、close与try/finally清理;异常、取消和break路径都要测试。
  5. 发送数据send、异常throw或close会影响暂停点行为,但普通迭代仅靠next。把复杂双向生成器当普通列表可能隐藏控制流与错误路径。
  6. 测试首次调用是否触发副作用、部分消费、耗尽、重新创建、异常推进和清理。共享同一个生成器给多个并发消费者需要额外协作,不是天然线程安全队列。

手动走一遍

gen里先记录started再yield 1、yield 2;g=gen()后started仍空,next(g)才记录并返回1,list(g)只剩[2],再list(g)为空。重新gen()才能从头开始。

规模与取舍

输出n项至少O(n)时间;工作内存取决于保存状态与底层缓冲,简单计数生成器O(1),消费成list仍O(n)输出空间。

易错点与追问

容易失分的边界

  • 创建生成器便执行全部函数体。
  • 二次消费期望从头开始。
  • 生成器内部全量读取却声称常量存储。

继续深挖

  • 提前break怎样释放文件?
  • yield from怎样传播结果和异常?
  • async generator与同步有何生命周期差别?

技术参考

✓已复制微信号!