返回实例列表没有区别?性能怎么样?

时间:2016-07-05 13:06:49

标签: python performance return

我刚刚意识到,对于我的程序中的特定模块,返回或不返回实例列表根本没有任何区别。使用固定种子,结果是相同的。

因此,我想知道:

  1. 包含return语句似乎是更好的编程习惯。这是对的吗?

  2. 我主要担心的是表现。我很难计时,因为似乎计算机中正在发生的其他事情似乎会影响结果。我得到4分3秒然后我得到5分钟而没有改变一个逗号。

  3. 请参阅以下示例:

    有一个大型函数从另一个模块调用,并传递了许多包含不同实例对象的列表:

    def check_demographics(month, my_agents, families, firms, my_graveyard, year, mortality_men, mortality_women, fertility, state_id):
    

    在该功能中,我有以下功能:

    def mortal(my_agents, my_graveyard, families, agent, firms):
        my_agents.remove(agent)
        my_graveyard.append(agent)
        families[agent.get_family_id()].death_member(agent)
        if families[agent.get_family_id()].num_members() == 0:
            families[agent.get_family_id()].empty_house()
        if agent.is_employed():
            firms[agent.get_workplace()].obit(agent)
        return my_agents, families, firms, my_graveyard 
    

    在上面的例子中,我发现返回是可选的。返回包含代理,族等的列表没有区别

    所以,我知道这个例子不可重复,但问题与一般事实有关。

    我假设列表在内存中的某个位置。

    P.S。我不是计算机科学家,而是研究人员试图做一些基于代理的建模。谢谢!

1 个答案:

答案 0 :(得分:3)

原则上,不返回任何东西都会更快。在实践中,它不重要,并且是无用的微优化。

Python不会在对象周围移动,它会将引用移动到对象(存储在名称中)。如果你有C ++背景,可以考虑return a,b,c给出一个由三个指针组成的数组。与您的函数正在执行的所有其他显式操作相比,此性能开销可以忽略不计。

如果您担心表现,您也不应该计划时间。 个人资料您的计划,以找出您的计划相当多的时间花在哪里。或 time 测试代码,以了解如何更好地执行关键代码(通过分析确定)。一个起点是用于计时代码的timeit包,以及各种python profilers,例如vmprof

例如,为了找出return的一般开销,你可以用这个明确的陈述:

$ python3 -m timeit -s 'def foo():' -s '  pass' 'foo()'
10000000 loops, best of 3: 0.0994 usec per loop
$ python3 -m timeit -s 'def foo():' -s '  return' 'foo()'
10000000 loops, best of 3: 0.0981 usec per loop
$ python3 -m timeit -s 'def foo():' -s '  return 1, 2' 'foo()'
10000000 loops, best of 3: 0.0961 usec per loop
$ python3 -m timeit -s 'bar, foo=object(), object()' -s 'def foo():' -s '  return foo, bar' 'foo()'
10000000 loops, best of 3: 0.136 usec per loop

你是否不返回,什么都不返回(隐式None)或返回常数并不重要。如果您实际返回对象,则会增加大约0.04 usec(!!!)的开销。只是调用一个函数已经是性能的2.5倍。

从编码风格的角度来看,IMO对python标准库的看法是最好的:如果某些内容发生了原因,就不要返回它。这强调了通过副作用改变了对象,没有必要创建对它们的新引用。