内嵌函数和闭包

函数的嵌套

python的函数支持内嵌,即在函数中定义函数

>>> def fun1():
	print('fun1()正在被调用')
	def fun2():
		print('fun2()正在被调用')
	fun2()

	
>>> fun1()
fun1()正在被调用
fun2()正在被调用

内嵌函数的作用域在外部函数之内,即fun2只能在fun1之内调用。

>>> fun2()
Traceback (most recent call last):
  File "<pyshell#7>", line 1, in <module>
    fun2()
NameError: name 'fun2' is not defined

闭包(closure)

闭包(Closure)是词法闭包(Lexical Closure)的简称,是引用了自由变量的函数。这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外。所以,有另一种说法认为闭包是由函数和与其相关的引用环境组合而成的实体。【光看文字说明比较难以理解】

>>> def funx(x):
	def funy(y):
		return x * y
	return funy

>>> funx(5)
<function funx.<locals>.funy at 0x0000006AB7FDD7B8>
>>> funx(4)(8)
32

我们发现,funx是一个函数,包括一个参数x。

比较特殊的地方是这个函数里面又定义了一个新函数funy,这个新函数里面的一个变量正好是外部函数funx的参数。

也就是说,外部传递过来的参数已经和funy函数绑定到一起了。

我们可以把x看做新函数的一个配置信息,配置信息不同,函数的功能就不一样了,也就是能得到定制之后的函数。

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

##注意:之前学过的局部变量、全局变量是相对而言。在函数的嵌套中,外部函数的变量对内部函数来说,也是不能更改其值的。##

>>> def fun1():
	x = 2
	def fun2():
		x += x
	return fun2()

>>> fun1()
Traceback (most recent call last):
  File "<pyshell#22>", line 1, in <module>
    fun1()
  File "<pyshell#21>", line 5, in fun1
    return fun2()
  File "<pyshell#21>", line 4, in fun2
    x += x
UnboundLocalError: local variable 'x' referenced before assignment

#这个例子中,x对fun2来说是一个全局变量,因此fun2中对x的调用被python shadowing保护了,在fun2内新建了一个跟x同名的局部变量
#因此当fun2想改变x的值时python会报错,提示局部变量不能在赋值之前调用

  

##对于以上问题有一个解决方法,就是把外部变量的值储存在某种容器中(例如列表、元组等),因为容器不会被shadowing【为什么?】##

>>> def fun1():
	x = [2]
	def fun2():
		x[0] += x[0]
		return x[0]
	return fun2()

>>> fun1()
4

##在Python3中对此又做了改进,直接发明了一个nonlocal,用来声明内部函数中的变量不是局部变量##

>>> def fun1():
	x = 2
	def fun2():
		nonlocal x
		x += x
		return x
	return fun2()

>>> fun1()
4

思考 nonlocal 和 global 的作用很类似,区别在哪里?作用范围?

原文地址:https://www.cnblogs.com/ginsonwang/p/5252379.html