例子

示例1

1
2
3
4
5
6
7
8
9
10
11
12
13
# 嵌套函数声明了自己的局部变量,所以不会找到外部函数的局部变量,对外面的局部变量也不会产生影响
def outFunc():
a = 1
def inFunc():
a = 2
print('from inFunc: a =',a)
inFunc()
print('from outFunc: a =',a)
outFunc()

# 输出:
from inFunc: a = 2
from outFunc: a = 1

示例2

1
2
3
4
5
6
7
8
9
10
11
12
# 嵌套函数找不到局部变量时找全局变量,这里指外部函数的局部变量
def outFunc():
a = 1
def inFunc():
print('from inFunc: a =',a)
inFunc()
print('from outFunc: a =',a)
outFunc()

# 输出:
from inFunc: a = 1
from outFunc: a = 1

示例3

1
2
3
4
5
6
7
8
9
10
11
12
13
def outFunc():
a = 1
def inFunc():
a = a+1
print('from inFunc: a =',a)
inFunc()
print('from outFunc: a =',a)
outFunc()

# 输出:
UnboundLocalError: local variable 'a' referenced before assignment
# 说明:
# 变量引用前赋值,这里要修改a的值,但外部函数的变量只可引用不可修改,所以认为a是局部变量,可a还没赋初始值,所以无法执行加1操作

示例4

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def outFunc():
a = 1
def inFunc():
nonlocal a
a = a+1
print('from inFunc: a =',a)
inFunc()
print('from outFunc: a =',a)
outFunc()

# 输出:
from inFunc: a = 2
from outFunc: a = 2
# 说明:
# 当内部作用域想修改外部作用域的变量时,就要用到 global 和 nonlocal 关键字了。
# 利用nonlocal关键字声明a不是局部变量,这样可以在嵌套函数中对其进行修改

示例5

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
def outFunc():
a = [1,2,3,4]
def inFunc():
a[1]=9
print('from inFunc: a =',a)
inFunc()
print('from outFunc: a =',a)
outFunc()

# 输出:
from inFunc: a = [1, 9, 3, 4]
from outFunc: a = [1, 9, 3, 4]
# 说明:
# a是外部函数的局部变量,可以看到最后被修改了,这是因为嵌套函数不能修改全局变量的本质是不能修改全局变量的指向,即不能将全局变量指向新的数据
# 因为a的指向并没有变,所以正常运行

总结:

  1. 嵌套函数不能修改全局变量,本质为不能修改全局变量的指向,即不能将全局变量指向新的数据
  2. 如果在嵌套函数中修改全局变量,那么就需要使用global或nonlocal进行声明,否则出错
  3. 对于不可变类型的全局变量来说,因其指向的数据不能修改,所以不使用global或nonlocal声明时无法修改全局变量
  4. 对于可变类型的全局变量来说,因其指向的数据可以修改,所以不使用global或nonlocal时也可修改全局变量

遗留问题:

  1. global vs nonlocal

  2. 不可变数据类型 vs 可变数据类型