【问题标题】:Python list comprehension - Directly returning large list is faster than storing, then returningPython列表理解 - 直接返回大列表比存储更快,然后返回
【发布时间】:2021-07-15 18:52:54
【问题描述】:

我最近正在处理一个问题,该问题需要我浏览一个非常大的文件夹(约 600,000 个文件)并返回符合特定标准的文件名列表。原始版本是存储在变量中的普通列表推导。这不是实际代码,但它提供了要点。

    def filter_files(file_path):
      filtered = [f.path for f in os.scandir(file_path) if f.path.endswith('.png')]
      return filtered

当监控这个时,它会开始很快,然后逐渐变得越来越慢。我猜是因为它只是想在变量中存储这么多数据。

然后我把它改写成:

    def filter_files(file_path):
      return [f.path for f in os.scandir(file_path) if f.path.endswith('.png')]

并称它为:

    def test(file_path):
      filtered = filter_files(file_path)

这个永远不会慢下来。它始终保持相同的速度。

我的问题是导致这种差异的原因是什么?数据仍然存储在变量中,并且仍然作为列表理解进行处理。如果在 return 中写出理解来避免第一个版本的问题呢?谢谢!

【问题讨论】:

  • 这两段代码没有区别。一个都没有。他们都在创建一个列表,然后管理对该列表的引用。您的代码中一定有其他事情发生。
  • 我假设这与您机器磁盘缓存中已经存在的一些文件有关,与您的 Python 代码无关。
  • 它会“快速启动”是什么意思?你怎么知道这个?
  • @Cruncher 我使用 tqdm 来监控估计的时间和每秒的迭代次数。
  • @chepner 感谢您的澄清,我认为他们的行为不同似乎很奇怪

标签: python performance return list-comprehension


【解决方案1】:

这两段代码没有区别。一个都没有。他们都在创建一个列表,然后管理对该列表的引用。

问题的可能原因是缓存。在第一种情况下,文件系统必须一遍又一遍地访问磁盘以获取更多条目。完成后,该目录位于文件缓存中,可以立即读取。重新启动并重试,您会看到第二个所需的时间相同。

【讨论】:

  • 您还可以使用dis 模块来验证两个函数定义是否生成相同的字节码。不必要的分配会被优化掉。
  • @Tim Roberts 嗯,这是有道理的。我想说我直接尝试在两者之间来回切换并且仍然有明显的差异,但是我可能只在第二个之前运行了第一个。感谢您的回答
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-04-01
  • 2023-04-08
  • 2016-01-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多