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

Python中构造持有N个独立类实例的最Pythonic实现方式

结论先行

你现在用的列表推导写法本身就是最Pythonic的标准实现,完全没必要刻意修改:

things = [lib.Thing() for _ in range(NUM_THINGS_TO_CREATE)]

针对你两个顾虑的说明

  • 关于_变量:这不是无意义的冗余写法,是Python全生态通用的约定标识,专门用来标记「循环、解包操作中不需要被后续逻辑引用的丢弃值」。所有熟悉Python的开发者看到_都会立刻明白这个位置的值不需要关注,反而能提升代码可读性,不存在“不优雅”的问题。
  • 关于[]列表容器:你的使用场景(构造多线程实例、需要持有实例引用、仅要求可迭代)下,列表是最优选择:
    • 列表推导会立刻完成所有实例的构造,不存在延迟初始化的问题
    • 列表会持有所有实例的强引用,只要列表本身不被回收,内部的Thread实例就不会被垃圾回收,能避免线程运行时出现无厘头的异常
    • 列表只存储实例的内存引用,单条引用仅占8字节左右,哪怕创建上万个实例,列表本身的内存开销也可以忽略
    • 列表天然支持迭代,完全满足你对容器的要求

可选调整方案(非必须)

如果你实在对_或者列表有抵触,可以参考以下方案,注意避开常见坑:

  • 不想在业务代码里看到_的话,可以把批量构造逻辑封装成通用工具函数,调用层就不会出现丢弃变量:
    from itertools import repeat
    def batch_init(cls, count):
        return [cls() for _ in repeat(None, count)]
    
    things = batch_init(lib.Thing, NUM_THINGS_TO_CREATE)
    
  • 如果你不需要后续对实例集合做增删、索引操作,也可以用不可变元组存储,效果和列表一致:
    things = tuple(lib.Thing() for _ in range(NUM_THINGS_TO_CREATE))
    
  • 绝对不要踩的坑:别为了省掉方括号直接把列表推导改成生成器表达式(把[]换成()):
    # 严重错误写法,禁止在该场景使用
    things = (lib.Thing() for _ in range(NUM_THINGS_TO_CREATE))
    
    生成器是惰性执行的,写完这行代码时不会创建任何实例,只有迭代things时才会逐个构造对象;如果迭代时没有额外持有实例引用,刚创建的对象会立刻被GC回收,在多线程场景下会直接导致线程异常退出,问题极难排查。

最后提一句:针对你构造线程实例的场景,只要保证持有实例的容器生命周期覆盖所有线程的运行周期即可,你原本的列表推导写法足够简洁、可靠,不需要为了“看起来更高级”刻意改成冷门写法。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 11:31:11