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修饰

内部函数可以修改外部变量(引用对象)的属性或元素

当形参(函数参数)与外部变量或全局变量名称相同时,此时形参变量生效,忽略其他地方的同名变量