Python手记:global 和 nonlocal的区别

文章目录

  • 一、Python的定义域
  • 二、global的作用
  • 三、nonlocal的作用
  • 四、闭包
  • 总结


学习过程中,我们会遇到两个有趣的关键字,一个是global,一个是nonlocal。

如果直接对英文进行翻译,一个会被翻译成“全局”,一个被翻译成“非局部”。

无论怎么想,都感觉两个意思差不多。这就很有趣了,就像是在讨论“美”和“不丑”的区别。

其实两个关键字功能都是在划定变量的定义域,需要视场景需要而定。

一、Python的定义域

先试看一个例子:

>>> b = 1
>>> def f():
		print(b)

	
>>> f()

特别简单,一下就得出了结果。f函数输出了全局变量b的值1。

Python手记:global 和 nonlocal的区别_第1张图片
来看第二个例子:

>>> b = 1
>>> def f():
	print(b)
	b = 2

	
>>> f()

与上一个例子相比,f函数中,多了一步对变量b的赋值。那它的结果是什么呢?

首先输出全局变量b的值1,然后对b重新赋值2?

错了:
Python手记:global 和 nonlocal的区别_第2张图片
结果是无法运行,原因是局部变量b未定义。

嘿,这就奇怪了。第一个例子里面我也没有定义局部变量b,怎么它就能去找全局变量b呢?

这就要说到Python的变量作用域规则:假定函数定义体中赋值的变量是局部变量

换而言之啊,因为“b=2”语句的存在,让Python认定f中的b属于局部变量。

二、global的作用

那如何在函数中使用全局变量呢?用global标记一下:
Python手记:global 和 nonlocal的区别_第3张图片
告诉函数,这个变量是个全局变量,接下来的操作都是对全局变量b而言的。

全局的问题解决了,再来看另外一个例子:

>>> def f():
	count = 0
	def a():
		count += 1
		print(count)
	return a()

>>> f()

猜猜看结果是什么?

有了前面的分析,这个例子就很好得出结果了。依旧是报错嘛。

因为函数a中,对count变量进行了赋值,所以Python认定count是局部变量,但在执行“count + 1”操作时,却没有找到count,所以报错了。

那怎么处理呢?

三、nonlocal的作用

我猜你会用global标记一下,但是注意啊。global标记的是全局变量,而这个例子中的count是a函数上一级f函数的变量,并不是全局变量。

Python手记:global 和 nonlocal的区别_第4张图片
对比global,这里要用 nonlocal标记,告诉a函数,count不在本地定义,但也不在全局变量里。

Python手记:global 和 nonlocal的区别_第5张图片

四、闭包

这个词想必在学习过程中一直听到,它是什么意思呢?简单来说啊,闭包是指延伸了作用域的函数

我们回头看最后一个例子:

>>> def f():
	count = 0
	def a():
		nonlocal count
		count += 1
		print(count)
	return a()

>>> f()

调用函数f时,f会返回a(),当执行a()的时候,f函数的任务已经完成了,它占用的资源就会释放掉,这其中包括了函数f环境中定义的count变量。

也就是说,在执行a的时候,函数f已经“撒手人寰”了,没有办法再去找到其中的数据。

像函数a中count这一类,不在本地定义域中绑定的变量,我们叫做自由变量。(和线性代数里的自由变量没关系哈。)

用nonlocal标记后呢,Python就会保留自由变量的绑定(或者说定义环境)。

因此最后例子中,整个函数a的作用域是“count = 0”,加上a本身。

因为a延伸了自己的作用域,所以这里就可以被称作“闭包”。

总结

global和nonlocal的功能都是改变变量作用域

global标记全局变量,nonlocal标记非全局、非本地的自由变量

延伸了作用域的函数,被称作“闭包”

你可能感兴趣的:(python手记)