学习关键字 global
和 nonlocal
的用法。
引例
先来看一个代码片段:
1 | increment = lambda x: x + 1 |
当运行上述代码片段时,会产生如下的错误:
1 | UnboundLocalError: local variable 'n' referenced before assignment |
要理解这个错误的原因,需要知道全局变量和局部变量的概念。
局部变量和全局变量
局部变量
当我们在函数体内、或者在局部范围内定义一个变量时,该变量被称为 局部变量
。局部变量只能在局部范围内被访问,不能在局部范围外被访问。
例1:在范围外访问局部变量
1 | def foo(): |
输出:
1 | local |
全局变量
当我们在函数外、或者在全局范围内定义一个变量时,该变量被称为 全局变量
。全局变量可以在函数内部被访问,也可以在函数外部被访问。
让我们来看一个全局变量的例子:
例3:全局变量
1 | x = "global" |
输出:
1 | x inside: global |
在上述代码中,x
是一个全局变量,我们可以在函数 foo
内部访问 x
,也可以在函数外部访问 x
。
值得注意的是,在上面的代码中,我们仅仅只是访问 x
。但如果我们想要做的是修改 x
的值呢?
例4: 在函数内部修改全局变量
1 | x = "global" |
Output
1 | UnboundLocalError: local variable 'x' referenced before assignment |
运行会出现错误。
这是因为,当我们在函数内部对 x
修改重新赋值时,Python解释器会认为 x
是局部变量而不是全局变量,而这个局部变量也并没有在函数内部定义,所以就产生了这个错误。
关键字:global和nonlocal
global关键字
为了解决例4的问题,我们使用 global 关键字。现在函数内部声明变量 x
是全局变量,再对其进行修改。代码如下:
1 | x = "global" |
输出:
1 | globalglobal |
nonlocal关键字
比较以下两个代码:
例5:不使用nonlocal关键字
1 | def func1(): |
输出:
1 | variable 2 |
例6:使用nonlocal关键字
1 | def func2(): |
输出:
1 | variable 2 |
注意到例6的第4行代码,嵌套函数 foo
中的变量 name
使用了关键字 nonlocal 。
如果一个变量被 nonlocal 修饰,则标识了该变量是上一级函数中的局部变量,在这里,指的是函数 func2
中的同名的变量 name
(line 2) 。因此在嵌套函数 foo
中修改变量 name
的值也就修改了 func2
中变量 name
的值。
而在例5中,嵌套函数 foo
中的变量 name
并没有用 nonlocal 修饰,那么它仅仅是 foo
中的一个局部变量。在函数 foo
的范围外是不能访问这个变量的。所以第7行打印的是第2行定义的局部变量 name
, 而不是第4行的局部变量。
尾声
最后让我们重新看一下引例中的代码:
1 | increment = lambda x: x + 1 |
要怎样修改才能使代码工作呢?
答案不唯一,但一个可行的办法是使用 nonlocal
关键字来修饰变量 n
, 如下所示:
1 | def make_repeater(func, n): |
🌼 完结,撒花 ✿✿ヽ(°▽°)ノ✿