- 函数只是一段可执行的代码,编译后就不能改变了,每个函数在内存中只能有一份实例,得到函数的入口点便可以执行函数了。函数还可以嵌套定义,即在函数内部可以定义另外一个函数,有了嵌套函数这中结构,便会产生闭包问题。
函数嵌套
- 在函数中还可以定义函数,可以嵌套多层,执行需要被调用。
def outer():
print('outer----hello')
def inner(): # inner这个函数是在outer函数内部定义的
print('inner----hello')
inner() # inner函数只在outer函数内部可见
outer()
# inner() 这里会报错,在outer函数外部无法访问到inner函数
什么是闭包
- 闭包是由函数及其相关引用环境组合而成的实体(即:闭包=函数块+引用环境)。
def outer(n):
num = n
def inner():
return num+1
return inner
print(outer(3)()) # 4
print(outer(5)()) # 5
在这段程序中,函数inner是函数outer的内嵌函数,并且inner函数是outer函数的返回值,我们注意到一个问题:内嵌函数inner中引用到外层函数的局部变量num,python解释器会怎么处理这个问题呢?我们先看看这段代码的运行结果,当我们调用分别由不同的参数调用outer函数得到的函数时,得到的结果时隔离的(相互不影响),也就是说每次调用outer函数后都将生成并保存一个新的局部变量num,这里outer函数返回的就是闭包。
- 如果在一个内部函数里,对外部作用域(但不是在全局作用域)的变量进行引用,那么内部函数就被认为时闭包。
修改外部变量的值
- 闭包里默认不能修改外部变量。
def outer(n):
num=n
def inner():
def inner():
num=num+1
return num
return inner
print(outer(1)())
这个代码会报错,在python里,只要看到了赋值语句,就会认为赋值语句的左边是一个局部变量。num = num + 1 这段代码里,num 在=的左边,python解析器会认为我们要修改inner函数里num这个局部变量,而这个变量使用之前是未声明的,所以会报错。
- 如何解决?
报错的原因在于当我们在闭包内修改外部变量时,会被python解析器误会为内部函数的局部变量。所以,解决方案就在于,我们需要想办法,让解析器知道我们不是要修改局部变量,而是要修改外部变量。
解决方法 :使用 nonlocal关键字
def outer(n):
num = n
def inner():
nonlocal num # 修改前使用nonlocal关键字对 num 变量进行说明
num = num + 1
return num
return inner
print(outer(2)())