函数:内嵌函数和闭包

global 关键字
上面提到在函数内部去修改全局变量的时候,会创建一个和全局变量名字一样的局部变量,真正的全局变量的值没有发生变化,这其实是python使用屏蔽的方式保护了全局变量。
但如果真的需要函数试图去修改全局变量,可以使用global关键字达到目的,例如:

>>> count = 5
>>> def  fun():
	global count
	count = 10
	print(count)

	
>>> fun()
10
>>> count
10

内嵌函数
允许在函数内创建另外一个函数,成为内嵌函数或内部函数,内部函数整个作用域在外部函数之内。
注意:内部函数只能在外部函数体中被随意调用,出了这个函数体,就没有任何函数可以对内部函数进行调用,不然就会报错。

闭包 closure
闭包是函数式编程的一个重要的语法结构。
python的闭包从表现形式上定义为:如果在一个内部函数里,在对外部作用域的变量进行引用,那么内部函数就被认为是闭包。

>>> def funX(x):
	def funY(y):
		return x*y
	return funY

>>> i = funX(8)
>>> i(5)
40
>>> 

在一个内部函数里对外部作用域的变量进行引用,比如上述X就是被引用的变量,x在外部作用域funX函数里面,但不再全局作用域内,则这个内部函数funY是一个闭包。
在闭包中,外部函数的局部变量对应内部函数的局部变量,事实上相当于之前说的全局变量跟局部变量的关系,在内部函数中,只能对外部函数的局部变量进行访问,不能进行修改。

>>> def funX():
	x = 5
	def funY():
		x *= x
		return x
	return funY

>>> funX()()
Traceback (most recent call last):
  File "<pyshell#22>", line 1, in <module>
    funX()()
  File "<pyshell#21>", line 4, in funY
    x *= x
UnboundLocalError: local variable 'x' referenced before assignment

这个报错与之前说全局变量的时候一样,python认为内部函数的x是局部变量,外部函数的x就被屏蔽起来,所以执行x *= x的时候,右边根本找不到局部变量x的值,因此报错
在python3以前,只能间接通过容器类型来存放,因为容器类型不是放在栈里,所以不会被屏蔽掉

>>> def funX():
	x = 5
	def funY():
		x[0] *= x[0]
		return x[0]
	return funY

>>> funX()()
25

在python3中,使用关键字nonlocal,使用方法与global一致

>>> def funX():
	x = 5
	def funY():
		nonlocal x
		x *= x
		return x
	return funY

>>> funX()()
25

课后题
1.如果希望在函数中修改全局变量的值,应该使用什么关键字?
2.在嵌套的函数中,如果希望在内部函数修改外部函数的局部变量,使用什么关键字?
3.python的函数可以嵌套,但是注意访问的作用域问题,请问以下代码存在什么问题?

def outside():
    print('I am outside!')
    def inside():
        print('I am inside!')

inside()

4.为何代码A没有报错,代码B报错了呢?应该如何修改?
代码 A——

def outside():
    var = 5
    def inside():
        var = 3
        print(var)
        
    inside()
outside()

代码B——

def outside():
    var = 5
    def inside():
        print(var)
        var = 3
        
    inside()
outside()

5.请问如何访问funIn()呢?

def funOut():
    def funIn():
        print('宾果!你成功访问到我啦!')
    return funIn()

6.以下是闭包的一个例子,请你目测下会打印什么内容?

扫描二维码关注公众号,回复: 8917777 查看本文章
def funX():
    x = 5
    def funY():
        nonlocal x
        x += 1
        return x
    return funY

a = funX()
print(a())
print(a())
print(a())

解:
1.global关键字

2.nonlocal关键字

3.使用嵌套函数要注意一点就是作用域问题,inside() 函数是内嵌在 outside() 函数中的,别的函数体里是无法对其进行调用的

4.这里 outside() 函数里有一个 var 变量,但要注意的是,内嵌函数 inside() 也有一个同名的变量,Python 为了保护变量的作用域,故将 outside() 的 var 变量屏蔽起来,因此此时是无法访问到外层的 var 变量的。

5.只需要直接调用 funOut() 即可:
funOut()
宾果!你成功访问到我啦!

6.6 7 8

发布了138 篇原创文章 · 获赞 203 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qinshangwy/article/details/104022990