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