【问题标题】:Returning lists of instances makes no difference? And what about performance?返回实例列表没有区别吗?那么性能呢?
【发布时间】:2016-11-07 08:10:56
【问题描述】:

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

因此,我想知道:

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

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

请看下面的例子:

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

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 

在上述情况下,我发现返回是可选的。返回包含代理、家庭等的列表没有区别。

所以,我知道该示例不可重现,但问题与一般事实有关。

我假设列表在内存中的某个地方。

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

【问题讨论】:

  • 您的问题到底是什么?如果这就是你真的不需要返回列表的原因,那是因为你所有的操作都是就地操作。由于您将 REFERENCE 传递给列表,因此这些就地操作将在列表本身上完成,并且您传递的相同引用将受到影响。
  • 问题是:如果是可选的,我不需要return,对吧?其次,哪种方式更快(有或没有返回)。谢谢。
  • python 返回的是对这些对象的引用元组。与通过更多引用工作的整个函数的开销相比,这简直可以忽略不计。是否拥有return 取决于您的功能应该做什么;通常,python 避免返回已更改的输入以强调这一点。顺便说一句,你不应该time你的代码,你应该profile它。

标签: python performance return


【解决方案1】:

原则上,不返回任何东西会更快。在实践中,这无关紧要,而且是无用的微优化。

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

如果您担心性能,也不应该为您的程序计时。 profile 您的程序,以找出您的程序相当大的时间在哪里花费。或者 time 测试代码以找出如何更好地执行关键代码(通过分析识别)。一个起点是用于计时代码的 timeit 包,以及各种 python 分析器,例如 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 微秒(!!!)的开销。仅仅调用一个函数就已经是性能成本的 2.5 倍。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-02-02
    • 1970-01-01
    • 2015-09-10
    • 2022-08-06
    • 2021-12-26
    • 1970-01-01
    • 2013-04-05
    相关资源
    最近更新 更多