从父函数传递参数到嵌套函数 Python

6 投票
2 回答
8081 浏览
提问于 2025-04-17 14:39

这是我的代码:

def f(x):
    def g(n):
        if n < 10:
            x = x + 1
            g(n + 1)
    g(0)

当我计算 f(0) 的时候,会出现一个错误:“x 在赋值之前被引用”。

但是,当我用“print x”替代“x = x + 1”时,它就能正常工作。

看起来在 g 的范围内,我只能把 x 当作“使用”的情况,而不能当作“绑定”的情况。我猜问题在于 f 只把 x 的值传给了 g。

我这样理解对吗?如果不对,能有人解释一下为什么“x = x + 1”的左边在引用之前没有定义吗?

谢谢

2 个回答

1

是的,给变量命名和读取它们的值是两回事。在一个函数里,如果你给某个名字赋值,那这个名字就被认为是这个函数的局部变量,除非你特别说明。

在Python 2中,唯一的“特别说明”方法是使用global语句,这样你就可以给全局变量赋值。在Python 3中,你还可以使用nonlocal语句来给一个更高层级(但不一定是全局的)作用域里的变量赋值。

在你的例子中,x是在一个更高层级但不是全局的作用域(就是函数f)。所以在Python 2中,你无法在g函数里给x赋值。而在Python 3中,你可以在g里用nonlocal x语句来做到这一点。

7

你理解得没错。在Python 2中,你不能在嵌套的作用域中使用x来进行赋值。

在Python 3中,你可以通过把变量标记为nonlocal来继续使用它进行绑定;这个关键词就是为了这个用途而引入的:

def f(x):
    def g(n):
        nonlocal x
        if n < 10:
            x = x + 1
            g(n + 1)
    g(0)

在Python 2中,你有一些变通的方法;可以使用可变对象来避免需要绑定,或者(滥用)函数属性:

def f(x):
    x = [x]   # lists are mutable
    def g(n):
        if n < 10:
            x[0] = x[0] + 1   # not assigning, but mutating (x.__setitem__(0, newvalue))
            g(n + 1)
    g(0)

或者

def f(x):
    def g(n):
        if n < 10:
            g.x = g.x + 1
            g(n + 1)
    g.x = x  # attribute on the function!
    g(0)

撰写回答