【问题标题】:More efficient ways of doing this更有效的方法
【发布时间】:2010-10-07 19:50:04
【问题描述】:
for i in vr_world.getNodeNames():
    if i != "_error_":
         World[i] = vr_world.getChild(i)

vr_world.getNodeNames() 返回一个巨大的列表,vr_world.getChild(i) 返回一个特定类型的对象。

这需要很长时间才能运行,有没有办法让它更有效率?在此之前,我已经看到单行循环应该更快。想法?

【问题讨论】:

  • .getNodeNames() 仅在您进入 for 循环时运行一次,因此如果需要一段时间,请修复它(如果可能)。不管你怎么做(例如列表推导——你提到的单行代码),大概你都必须得到函数以某种方式启动的数据。
  • 您是否通过分析器运行代码以找出其中的 部分 是慢的?
  • 是的,我认为这里没有任何问题。我将不得不探索 getNodeNames 背后的功能
  • @Daenyth:在 Python 标准库中是否有这样的功能?我可能只是使用time.time()'s...虽然在这个简单的python代码和两个黑盒函数上,它可能是什么并没有太多的争论。
  • @relima:看看wiki.python.org/moin/PythonSpeed/PerformanceTips#ProfilingCode。另外,如果您可以发布您正在调用的函数的定义,我们也许能够确定问题

标签: python optimization


【解决方案1】:

kaloyan 建议使用生成器。这就是为什么这可能会有所帮助。

如果getNodeNames() 构建一个列表,那么您的循环基本上会遍历列表两次:一次是构建它,一次是迭代列表时。

如果getNodeNames() 是生成器,那么您的循环永远不会构建列表;它不是创建项目并将其添加到列表中,而是创建项目并将其生成给调用者。

这是否有帮助取决于几件事。首先,必须可能getNodeNames() 实现为生成器。我们对该功能的实现细节一无所知,因此无法说是否是这种情况。接下来,您要迭代的项目数量需要非常大。

当然,如果所有这一切的耗时操作都是vr_world.getChild(),那么这一切都不会产生任何影响。这就是为什么你需要分析你的代码。

【讨论】:

    【解决方案2】:

    我认为你不能让它比你现有的更快。是的,你可以把整个东西放在一条线上,但这不会让它更快。瓶颈显然是getNodeNames()。如果你可以把它变成一个生成器,你将很快开始用结果填充World dict(如果这对你很重要),如果你让它过滤掉"_error_" 值,你将无法处理这个问题后期。

    【讨论】:

      【解决方案3】:
      World = dict((i, vr_world.getChild(i)) for i in vr_world.getNodeNames() if i != "_error_")
      

      这是一个单行,但不一定比您的解决方案快得多...

      【讨论】:

      • 这实际上是更高效还是更紧凑?
      • 这真的没有让事情变得更好——或更糟。也许问题出在 getChild 中。
      • @GWW,生成器表达式通常会比等效的 for 循环快 10% 到 100%,尽管我见过它们速度较慢的情况。
      • 很高兴知道这一点。这可能就是为什么我的一些文件解析代码需要永远感谢!
      【解决方案4】:

      也许您可以使用过滤器和地图,但我不知道这是否会更快:

      valid = filter(lambda i: i != "_error_", vr_world.getNodeNames())
      World = map(lambda i: vr_world.getChild(i), valid)
      

      此外,您会在这里看到很多情况,请先配置文件,然后再进行优化,否则您可能会浪费时间。你有两个函数,也许它们是慢的部分,而不是迭代。

      【讨论】:

      • 遗憾的是,在 python 中,filter/map 解决方案几乎总是比列表理解慢。
      • 如果速度是第一行的一个因素:valid = filter('_error_'.__eq__, vr_world.getNodeNames())
      • 此外,lambda 函数比常规函数慢,或者如上例中的内联逻辑。
      • 对于huge 列表,您应该真的使用来自itertools 的ifilterimap 来懒惰地处理它,而不必将所有内容都保存在内存中一次。对于非常大的列表,这可以节省大量时间。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-03
      • 2011-04-11
      • 2011-03-29
      • 2014-06-19
      • 2013-08-02
      • 1970-01-01
      相关资源
      最近更新 更多