【问题标题】:Python closure with side-effects具有副作用的 Python 闭包
【发布时间】:2011-09-27 19:36:06
【问题描述】:

我想知道 Python 中的闭包是否可以操作其命名空间中的变量。您可能会称其为副作用,因为状态正在闭包本身之外进行更改。我想做这样的事情

def closureMaker():
  x = 0
  def closure():
    x+=1
    print x
  return closure

a = closureMaker()
a()
1
a()
2

显然我希望做的事情更复杂,但这个例子说明了我在说什么。

【问题讨论】:

  • 我会将此标记为其他问题的重复,但其他问题确实应该标记为与此问题的重复;这个问题很简单,切中要害,写得很好。但也见stackoverflow.com/questions/141642/…
  • 那么有没有办法合并两个或多个问题? ;p

标签: python closures side-effects


【解决方案1】:

在 Python 2.x 中您不能完全做到这一点,但您可以使用一个技巧来获得相同的效果:使用可变对象,例如列表。

def closureMaker():
    x = [0]
    def closure():
        x[0] += 1
        print x[0]
    return closure

您还可以将 x 设为具有命名属性的对象或字典。这比列表更具可读性,尤其是当您有多个这样的变量要修改时。

在 Python 3.x 中,您只需将 nonlocal x 添加到您的内部函数中。这会导致对x 的分配转到外部范围。

【讨论】:

  • 请解释原因?我正在尝试在 python 文档中找到有关此的内容。
  • @André:PEP 3104 提供信息,如果是技术性的:python.org/dev/peps/pep-3104
  • 对我来说,它似乎应该工作。我刚刚读到this“如果定义出现在功能块中,则范围扩展到包含在定义块中的任何块,除非包含的块为名称引入了不同的绑定。”
  • 啊,所以当您尝试在问题中给出的示例中分配给x 时 - 它不起作用,因为您尝试 重新绑定 变量?偷偷摸摸。
  • @André:当一个变量在函数中被赋值时(这包括像+=这样的扩展赋值运算符),那么它就成为该函数的局部变量。所以在原代码中,xclosureMaker的局部变量(因为x=0),而another x变成了closure的局部变量(因为x+=1 )。使用列表代替时,closure 中的x 没有直接赋值,因此它使用与closureMaker 相同的变量。
【解决方案2】:

What limitations have closures in Python compared to language X closures?

nonlocal keyword in Python 2.x

例子:

def closureMaker():
     x = 0
     def closure():
         nonlocal x
         x += 1
         print(x)
     return closure

【讨论】:

    猜你喜欢
    • 2014-01-17
    • 1970-01-01
    • 2022-12-20
    • 2011-10-30
    • 2018-08-06
    • 2018-01-06
    • 2016-04-08
    • 2019-12-18
    • 1970-01-01
    相关资源
    最近更新 更多