【问题标题】:Python functional closures without performance hit没有性能影响的 Python 函数式闭包
【发布时间】:2015-06-27 16:39:12
【问题描述】:

在我的 python 程序中,我有很多函数实际上是更复杂函数的包装器(更复杂的函数需要更多参数,因此简单函数会计算额外的参数并将它们与原始参数一起传递给复杂函数职能)。我不希望从外部范围看到更复杂的功能。但是,我的理解是,如果每次调用外部函数时都在函数内部定义一个函数,那么它会重新定义内部函数,这是一种浪费。如何隐藏我的内在功能而不一遍又一遍地重新定义它们?解释器必须有某种方法来解析我的文件并只执行一次定义,但仍将它们保留在内部范围内。

【问题讨论】:

  • 为什么不使用__all__ 和/或命名约定(按约定私有的前导下划线)来控制包中import 可用的名称,而不是嵌套职能?然后你只定义一次,它们不是直接可用的并且你的结构变得更简单。
  • 把函数移出即可。如果必须,将其移至另一个模块。您没有必须将您的函数放在嵌套范围内。请注意,“性能影响”并不比任何其他对象创建更重要;您不会抱怨在函数中创建字符串或列表,但成本大致相同。
  • @jonrsharpe 需要明确的是,如果我有def a(): \n \t def b(): \n \t print foo,它不会在我每次调用a 时重新定义b
  • 所有 Python 所做的只是 a) 加载已编译的代码对象,b) 创建一个带有正确元数据和附加闭包的函数对象。这几乎不贵。
  • @RenéG:不,给定函数的代码不会改变。您没有生成该代码,它被编译一次。如果您使用if..else 进行分支,那么要么有多个代码对象可供选择,要么if...else 分支是编译代码的一部分

标签: python scope


【解决方案1】:

不要通过嵌套来控制对您的“内部函数”的访问,而是使用以下之一或两者:

  • 命名约定(名称的前导下划线表示按约定私有,请参阅the style guide);和
  • 定义一个名为__all__ 的列表以指定默认情况下从包中导入的内容(请参阅the tutorial on modules)。

使用中:

# define the names that get imported from this package
__all__ = ['outer_func']`

def _inner_func(...):
    """Private-by-convention inner function.""" 
    ...

def outer_func(...):
    """Public outer function to call _inner_func."""
    ...

这也使测试变得更加容易,因为您仍然可以在必要时直接访问_inner_func

【讨论】:

  • 我想我必须这样做;我的基准测试表明,在内部定义函数会使其速度降低约 3%,这对于如此小的语义改进来说确实是很多。
【解决方案2】:

我认为惯例是在函数名前加上两个下划线。

(参见:http://www.diveintopython.net/object_oriented_framework/private_functions.html

【讨论】:

  • 这不是真正的私有,只是“名称混乱”;根据the style guide,这应该“通常...仅用于避免与设计为子类的类中的属性发生名称冲突”
猜你喜欢
  • 2013-05-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-30
  • 1970-01-01
  • 2013-07-17
  • 1970-01-01
相关资源
最近更新 更多