【问题标题】:Efficient way of calling set of functions in Python在 Python 中调用函数集的有效方法
【发布时间】:2009-11-23 20:52:01
【问题描述】:

我有一组函数:

functions=set(...)

所有函数都需要一个参数x。

在 python 中执行类似操作的最有效方法是:

for function in functions:
   function(x)

【问题讨论】:

  • 那里的代码有什么问题?
  • 如果设置集合的规则允许,我会很想编写一个调度函数来按顺序进行适当的调用。这是一种更明确的方法。

标签: python iteration


【解决方案1】:

你给的代码,

for function in functions:
    function(x)

...调用function(x) 的结果似乎没有任何作用。如果确实如此,这意味着调用这些函数是因为它们的副作用,那么就没有更多的 Pythonic 替代方案了。 保持你的代码不变。这里要带回家的重点是

避免使用列表理解中具有副作用的函数。

至于效率:我希望使用其他任何东西而不是简单的循环不会提高运行时间。如有疑问,请使用timeit。例如,以下测试似乎表明常规 for 循环比列表理解更快。 (我不愿意从这个测试中得出任何一般性结论,想):

>>> timeit.Timer('[f(20) for f in functions]', 'functions = [lambda n: i * n for i in range(100)]').repeat()
[44.727972984313965, 44.752119779586792, 44.577917814254761]
>>> timeit.Timer('for f in functions: f(20)', 'functions = [lambda n: i * n for i in range(100)]').repeat()
[40.320928812026978, 40.491761207580566, 40.303879022598267]

但同样,即使这些测试表明列表理解更快,但为了便于阅读,在涉及副作用时,您不应该使用它们。


  :好吧,我会写成for f in functions,这样functionfunctions 之间的区别就更明显了。但这不是这个问题的目的。

【讨论】:

  • +1 用于“避免在列表理解中具有副作用的函数”提醒。
  • 特别是因为没有定义迭代集合成员的顺序
【解决方案2】:

如果您需要输出,列表推导可以工作。

[func(x) for func in functions]

【讨论】:

    【解决方案3】:

    我有点怀疑这会对你的程序的总运行时间产生多大的影响,但我想你可以这样做:

    [func(x) for func in functions]
    

    缺点是您将创建一个新列表并立即丢弃,但它应该比 for 循环稍快。

    在任何情况下,请确保您分析您的代码以确认这确实是您需要处理的瓶颈。

    【讨论】:

    • 列表解析应该比for 循环更快并没有什么特别的原因。此类声明需要基准。
    • wiki.python.org/moin/PythonSpeed/PerformanceTips#Loops 似乎表明有一个特殊原因,即循环被推入编译的 C 代码中。诚然,还有其他因素也有影响,这就是为什么我告诉他进行分析。
    【解决方案4】:

    编辑:我使用 timeit 重新进行了测试

    我的新测试代码:

    import timeit
    
    def func(i):
        return i;
    
    a = b = c = d = e = f = func
    
    functions = [a, b, c, d, e, f]
    
    timer = timeit.Timer("[f(2) for f in functions]", "from __main__ import functions")
    print (timer.repeat())
    
    timer = timeit.Timer("map(lambda f: f(2), functions)", "from __main__ import functions")
    print (timer.repeat())
    
    timer = timeit.Timer("for f in functions: f(2)", "from __main__ import functions")
    print (timer.repeat())
    

    这是这个时间的结果。

    testing list comprehension
    [1.7169530391693115, 1.7683839797973633, 1.7840299606323242]
    
    testing map(f, l)
    [2.5285000801086426, 2.5957231521606445, 2.6551258563995361]    
    
    testing plain loop
    [1.1665718555450439, 1.1711149215698242, 1.1652190685272217]
    

    我原来的基于 time.time() 的计时与这个测试几乎一致,简单的 for 循环似乎是最有效的。

    【讨论】:

      猜你喜欢
      • 2018-03-21
      • 1970-01-01
      • 2019-07-27
      • 2016-07-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-19
      相关资源
      最近更新 更多