带有副作用的Python闭包

Mik*_*ike 9 python closures side-effects

我想知道Python中的闭包是否可以操作其命名空间中的变量.你可能会称这种副作用,因为状态在闭包本身之外被改变了.我想做这样的事情

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

a = closureMaker()
a()
1
a()
2
Run Code Online (Sandbox Code Playgroud)

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

int*_*jay 17

你无法在Python 2.x中做到这一点,但是你可以使用技巧来获得相同的效果:使用可变对象,例如列表.

def closureMaker():
    x = [0]
    def closure():
        x[0] += 1
        print x[0]
    return closure
Run Code Online (Sandbox Code Playgroud)

您还可以使用命名属性或字典使x成为对象.这比列表更具可读性,特别是如果您要修改多个此类变量.

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

  • @André:当一个变量被赋值给一个函数(这包括增强赋值运算符,如`+ =`)时,它就成了该函数的局部变量.所以在原始代码中,`x`是`closureMaker`的局部变量(因为`x = 0`),而***是一个局部变量`closure`(因为`x + = 1`) .当使用列表时,在`closure`中没有直接赋值给`x`,因此它使用与`closureMaker`相同的变量. (2认同)