带有副作用的Python闭包

带有副作用的Python闭包,python,closures,side-effects,Python,Closures,Side Effects,我想知道Python中的闭包是否可以操纵其名称空间中的变量。您可以称之为副作用,因为状态在闭包本身之外发生了更改。我想做这样的事情 def closureMaker(): x = 0 def closure(): x+=1 print x return closure a = closureMaker() a() 1 a() 2 显然,我希望做的事情更复杂,但这个例子说明了我所说的。在Python2.x中不能完全做到这一点,但可以使用一个技巧来获得相同的效果:使用

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

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

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

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

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

def closureMaker():
    x = [0]
    def closure():
        x[0] += 1
        print x[0]
    return closure
您还可以使x成为具有命名属性的对象或字典。这可能比列表更具可读性,尤其是当您要修改多个这样的变量时

在Python3.x中,您只需要向内部函数添加
非局部x
。这会导致
x的赋值转到外部作用域。

例如:

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

请解释一下原因?我正试图在python文档中找到一些关于这方面的信息。@André:PEP 3104是信息性的,如果是技术性的话:对我来说,它似乎应该是双向的。我刚刚读到:“如果定义发生在函数块中,范围将扩展到定义块中包含的任何块,除非包含的块为名称引入了不同的绑定。”啊,那么在问题中给出的示例中,当您尝试分配给
x
时,它不起作用,因为您尝试重新绑定变量?偷偷摸摸。@André:当一个变量被分配到一个函数中时(这包括增强的赋值运算符,如
+=
),那么它就是该函数的一个局部变量。因此,在原始代码中,
x
closureMaker
的局部变量(因为
x=0
),而另一个x是
closure
的局部变量(因为
x+=1
)。当使用列表时,在
closure
中没有对
x
的直接赋值,因此它使用了与
closureMaker
相同的变量。我会将此标记为其他问题的副本,但其他问题确实应该标记为此问题的副本;这个问题很简单,切中要害,写得很好。但也看到了,所以没有办法合并两个或多个问题;P