函数闭包与可调用类

max*_*max 12 python performance closures python-3.x

在许多情况下,有两种实现选择:闭包和可调用类.例如,

class F:
  def __init__(self, op):
    self.op = op
  def __call__(self, arg1, arg2):
    if (self.op == 'mult'):
      return arg1 * arg2
    if (self.op == 'add'):
      return arg1 + arg2
    raise InvalidOp(op)

f = F('add')
Run Code Online (Sandbox Code Playgroud)

要么

def F(op):
  if op == 'or':
    def f_(arg1, arg2):
      return arg1 | arg2
    return f_
  if op == 'and':
    def g_(arg1, arg2):
      return arg1 & arg2
    return g_
  raise InvalidOp(op)

f = F('add')
Run Code Online (Sandbox Code Playgroud)

在任何一个方向上做出选择时应该考虑哪些因素?

我能想到两个:

  • 似乎关闭总会有更好的表现(不能想到一个反例).

  • 我认为有些情况下关闭不能完成工作(例如,如果其状态随时间变化).

我在这些方面是否正确?还能添加什么?

Ray*_*ger 10

闭包更快.类更灵活(即比__call__更多的方法可用).

  • 抱歉,您的评论并未反映出对Python的正确理解.例如,您可以向类中添加__len__方法,或者可以将其作为函数属性附加到闭包中,但``len(obj)``只能用于前者. (5认同)
  • 我不同意这一点.你可以在Python中用表达闭包的对象添加你想要的任何东西(由于某些原因我不知道).由于object是Python语言的主要价值 - 获取值的方式(通过将代码片段作为对象或通过构造其他类的对象)之间没有太大的区别 - 它们都是对象.由于Python是动态语言,几乎任何对象都可以被修改(实际上我确实认为闭包不是其中之一). (3认同)
  • 一个人关闭的是自己的事业:-) (3认同)
  • @尤瓦尔。更快意味着它运行得更快。原因是闭包变量的查找比实例变量的查找更快(请参阅 https://code.activestate.com/recipes/577834 )。此外,调用方法需要创建绑定方法,但这对于闭包来说不是必需的。您可以运行 timeit.py 来说服自己这是真的:-) (2认同)
  • @batMan你是对的,OPs的例子并没有结束;然而,大多数关于性能的推理仍然成立。类样式的访问会产生属性查找开销,而嵌套函数样式使用局部变量和/或闭包单元变量,这两者都比属性访问更快。 (2认同)