“当在函数中给一个变量名赋值是(而不是在一个表达式中对其进行引用),Python总是创建或改变本地作用域的变量名,除非它已经在那个函数中被声明为全局变量. ”
1.定义的函数内部的变量名如果是第一次出现, 且在=符号前,那么就可以认为是被定义为局部变量。在这种情况下,不论全局变量中是否用到该变量名,函数中使用的都是局部变量。例如:
num = 100
def func():
num = 123
print num
func()
输出结果是123。说明函数中定义的变量名num是一个局部变量,覆盖全局变量。再例如:
输出结果是:UnboundLocalError: local variable 'num' referenced before assignment。提示错误:局部变量num在赋值前被应用。也就是说该变量没有定义就被错误使用。由此再次证明这里定义的是一个局部变量,而不是全局变量。
2.函数内部的变量名如果是第一次出现,且出现在=符号后面,且在之前已被定义为全局变量,则这里将引用全局变量。例如:
num = 100
def func():
x = num + 100
print x
func()
输出结果是200。如果变量名num在之前没有被定义为全局变量,则会出现错误提示:变量没有定义。例如:
def func():
x = num + 100
print x
func()
出结果是:NameError: global name 'num' is not defined。
3.函数中使用某个变量时,如果该变量名既有全局变量也有局部变量,则默认使用局部变量。例如:
num = 100
def func():
num = 200
x = num + 100
prinx x
func()
输出结果是300。
4.在函数中将某个变量定义为全局变量时需要使用关键字global。例如:
num = 100
def func():
global num
num = 200
print num
func()
print num
输出结果分别是200和200。这说明函数中的变量名num被定义为全局变量,并被赋值为200。再例如
num = 100
def func():
global num
num = 200
num += 100
print num
func()
print num
输出结果分别是300和300。变量作用域
变量作用域(scope)在Python中是一个容易掉坑的地方。
Python的作用域一共有4中,分别是:
L (Local) 局部作用域
E (Enclosing) 闭包函数外的函数中
G (Global) 全局作用域
B (Built-in) 内建作用域
以 L --> E --> G -->B 的规则查找,即:在局部找不到,便会去局部外的局部找(例如闭包),再找不到就会去全局找,再者去内建中找。
Python除了def/class/lambda 外,其他如: if/elif/else/ try/except for/while并不能改变其作用域。定义在他们之内的变量,外部还是可以访问。
>>> if True:
... a = 'I am A'
...
>>> a
'I am A'
定义在if语言中的变量a,外部还是可以访问的。但是需要注意如果if被 def/class/lambda 包裹,在内部赋值,就变成了此 函数/类/lambda 的局部作用域。
在 def/class/lambda内进行赋值,就变成了其局部的作用域,局部作用域会覆盖全局作用域,但不会影响全局作用域。
g = 1 #全局的
def fun():
g = 2 #局部的
return g
print fun()
# 结果为2
print g
# 结果为1
但是要注意,有时候想在函数内部引用全局的变量,疏忽了就会出现错误,比如:
#file1.py
var = 1
def fun():
print var
var = 200
print fun()
#file2.py
var = 1
def fun():
var = var + 1
return var
print fun()
这两个函数都会报错UnboundLocalError: local variable 'var' referenced before assignment
在未被赋值之前引用的错误!为什么?因为在函数的内部,解释器探测到var被重新赋值了,所以var成为了局部变量,但是在没有被赋值之前就想使用var,便会出现这个错误。解决的方法是在函数内部添加 globals var 但运行函数后全局的var也会被修改。
关键子nonlocal
的作用与关键字global
类似,使用nonlocal
关键字可以在一个嵌套的函数中修改嵌套作用域中的变量,示例如下
def func():
count = 1
def foo():
count = 12
foo()
print(count)
func() #输出1
上面的程序中,在嵌套的foo函数中,对变量count赋值,同样会创建一个新的变量,而非使用count = 1
语句中的count,如果要修改嵌套作用域中的count,就要使用nonlocal
关键字了:
def func():
count = 1
def foo():
nonlocal count
count = 12
foo()
print(count)
func() #输出12
上面的程序中,在foo函数中使用了nonlocal
关键字,就会告诉Python在foo函数中使用嵌套作用域中的变量count,因此对变量count进行修改时,会直接影响到嵌套作用域中的count变量,程序最后也就输出12了.
注意:使用global
关键字修饰的变量之前可以并不存在,而使用nonlocal
关键字修饰的变量在嵌套作用域中必须已经存在。