安利一波这位大佬的博客安利写的真的不错,就是有点长基本看完就懂了,我这里给出自己的理解,外加一些大佬没有给出的测试情况。
一:global是标记此变量是全局变量
例如如下的程序
b = 12
def get():
return b
print(get())
12
上面段代码运行完全没有问题,但是下面这段:
b = 12
def get():
b = b + 2
return b
print(get()
就会报错。这是因为python3里面对全局变量只能引用不能修改,如果修改需要加上global声明。将上面这段代码改一下一下就可以得到正确的结果
b = 12
def get():
global b
b = b + 2
return b
print(get())
14
其实还有一个比较有趣的现象.如果函数外面没有声明变量,直接在函数里面用global声明一个变量,当调用了这个函数后,在外面也可以用这个变量了。
def get():
global b
b = 4
b = b + 2
return b
print(get())
print(b)
6
6
还有一个让我觉得有趣的现象:
L = [1, 2]
def get():
L.append(3)
return L
print(get())
print(L)
[1, 2, 3]
[1, 2, 3]
以上这段代码没有用global声明,貌似好像也能’修改’函数外面的变量?
其实本质上说get()函数并没有修改L,对于list这类可变变量来说,对其删除和添加元素并不能算是修改该变量。,对于L来说其指向的对象并没有改变,只是对象本身变了而已。举个例子,这就像在调用get函数之前我找的是小明同学,在调用get()函数后,我找的是多穿了一件衣服的小明同学。
L = [1, 2]
def get():
L = 2
return L
print(get())
print(L)
2
[1, 2]
这段代码并没有报错,因为get()函数内部的L看成了初始化了一个局部变量的操作,而全局的L并没有改变。
L = [1, 2]
def get():
global L
L = 2
return L
print(get())
print(L)
2
2
以上代码就会修改外部的全局变量。
二:nonlocalb声明的变量,会从当前作用域的外层(该外层不能包括全局变量)寻找该变量。
b = 1
def get():
nonlocal b
b = b+10
return b
print(get())
print(b)
SyntaxError: no binding for nonlocal 'b' found
以上代码会报错,这个就是(该外层不包括全局)的意思。
b = 10
def get():
b = 20
def f():
b = b + 1
return b
print(f())
return b
print(get())
print(b)
UnboundLocalError: local variable 'b' referenced before assignment
这段代码会报错,但是如果在f函数内部加上nonlocal声明的话,就可以正常运行了输出是:21 21 10
如果把f函数内的加上global申明的话,输出就会变成:11 20 11。可以看出虽然变量名字一样,但只要加上global声明就会和最外层的全局变量绑定
b = 10
def get():
b = 20
def f():
b = 11
def w():
nonlocal b
b = -1
return b
print('w -> %d' % w())
return b
print('f -> %d' % f())
return b
print('get -> %d' % get())
print('b -> %d' % b)
w -> -1
f -> -1
get -> 20
b -> 10
上面这个函数和输出结果说明,nonlocal会绑定和当前作用域最近的那个变量。
b = 10
def get():
b = 20
def f():
def w():
nonlocal b
b = -1
return b
print('w -> %d' % w())
return None
f()
return b
print('get -> %d' % get())
print('b -> %d' % b)
w -> -1
get -> -1
b -> 10
这里发现即使相隔两层,但是仍然可以绑定到所需要的变量。
b = 10
def get():
def g():
b = 1
return 1
def f():
nonlocal b
b = 20
return b
print('g -> %d' % g())
print('f -> %d' % f())
return b
print('get -> %d' % get())
print('b -> %d' % b)
SyntaxError: no binding for nonlocal 'b' found
上面这段代码会报错,这个说明,对于并行的两个函数的变量,无法相互绑定。只有包含关系才可以。