1. 基本嵌套函数
一个函数内部可以包含子函数,并在内部调用
def main():
def sub():
print('sub')
print('main')
sub()
main()
结果
main
sub
2. 内部函数参照外部变量
def main():
var = 1
def sub():
print('sub-var: ' + str(var))
print('main-var: ' + str(var))
sub()
main()
结果
main-var: 1
sub-var: 1
3. 内部函数修改外部变量
3.1 失败例子1
直接修改外部变量var (编译阶段会提示报错)
def main():
var = 1
def sub():
var = var + 1
print('sub-var: ' + str(var))
print('main-var-begin: ' + str(var))
sub()
print('main-var-end: ' + str(var))
main()
期待结果
main-var-begin: 1
sub-var: 2
main-var-end: 2
实际结果: 异常 (实际上在pyCharm中也会有红线提示)
line 5, in sub
var = var + 1
UnboundLocalError: local variable ‘var’ referenced before assignment
原因分析
当一个函数内部出现变量赋值(比如 var=…)时,会忽视外部所有的变量,重新初始化一个函数内闭包的变量名,所以当出现 var = var + 1时, 提示等号后面的var没有初始值
3.2 失败例子2
将var用global修饰(编译阶段不会提示报错)
def main():
var = 1
def sub():
global var
var = var + 1
print('sub-var: ' + str(var))
print('main-var-begin: ' + str(var))
sub()
print('main-var-end: ' + str(var))
main()
期待结果
main-var-begin: 1
sub-var: 2
main-var-end: 2
实际结果: 异常
line 6, in sub
var = var + 1
NameError: name ‘var’ is not defined
原因分析
global用法的理解有错,以为是将sub函数外部的var变量提升成全局变量。正确的用法是:global关键字的意思是从独立于所有函数(包括这里的main()函数)的变量中去寻找指定的变量,这里正确的做法是使用
nonlocal
关键字
3.3 成功例子1
将var变量提提升为全局变量(与main()函数同级别)
var = 1
def main():
def sub():
global var
var = var + 1
print('sub-var: ' + str(var))
print('main-var-begin: ' + str(var))
sub()
print('main-var-end: ' + str(var))
main()
结果
main-var-begin: 1
sub-var: 2
main-var-end: 2
3.4 成功例子2
将var的当前值通过变量传入,sub函数中的var变量只是sub内部闭包的变量,与外部变量var没有任何关系,计算完成的值通过return
向外部传递, 在外部去修改变量值。
def main():
var = 1
def sub(var):
var = var + 1
print('sub-var: ' + str(var))
return var
print('main-var-begin: ' + str(var))
var = sub(var)
print('main-var-end: ' + str(var))
main()
结果
main-var-begin: 1
sub-var: 2
main-var-end: 2
3.5 成功例子3
外部变量的值不能改变(变量的引用的地址),但是可以更改其引用对象的值(修改其属性或者元素)
def main():
var = {'var': 1} # 这里可以为对象,数组,字典
def sub():
var['var'] = var['var'] + 1 # 只要不出现 var=... 即可
print('sub-var: ' + str(var['var']))
print('main-var-begin: ' + str(var['var']))
sub()
print('main-var-end: ' + str(var['var']))
main()
结果
main-var-begin: 1
sub-var: 2
main-var-end: 2
3.6 成功例子4
使用 nonlocal
关键字可以在内部函数中操作外部函数的变量
def main():
var = 1
def sub():
nonlocal var
var = var + 1
print('sub-var: ' + str(var))
print('main-var-begin: ' + str(var))
sub()
print('main-var-end: ' + str(var))
main()
4. 结论
从上面的例子可以得到以下结论
- 针对外部变量:
- 内部函数可以参照外部变量
- 内部函数可以修改外部变量(引用对象)的属性或元素
- 使用
nonlocal
关键字,内部函数可以替换外部变量(的引用)
- 针对全局变量:
- 内部函数可以参照全局变量
- 内部函数可以修改外部变量(引用对象)的属性或元素
- 使用
global
关键字,内部函数可以替换全局变量(的引用)
- 当形参(函数参数)与外部变量或全局变量名称相同时,此时形参变量生效,忽略其他地方的同名变量