Python 变量,以及global和nonlocal关键字
目录
- 变量作用域
- global
- 闭包与nonlocal
1. 变量作用域
作为一门动态语言,Python变量在使用的时候,不用申明变量类型,而是直接使用的。
>>> a = 123 >>> print(a) 123 >>> a = 'hello, Python' >>> print(a) hello, Python >>>
当我们在命令行敲入python3的时候,当期模块默认为
__main__。
>>> print(__name__) __main__ >>>
接下来,定义一个函数,对于函数而言,前面的变量a是外层变量,可以理解为默认模块
__main__的全局变量。
在函数foo中,直接访问变量a,最终在外层找到了a。如果在函数中给变量a赋值,会覆盖全局变量。
注意,这里相当于定义了一个局部变量a,而不是改写全局变量a。
>>> def foo(): ... print(a) ... >>> foo() hello, Python >>> >>> def foo(): ... a = 'in foo' ... print(a) ... >>> foo() in foo >>> >>> print(a) hello, Python >>>
但是下面的方式会报错,因为Python在编译函数bar的时候,会扫描整个函数体,生成字节码,然后执行。在生成字节码的时候,发现
a=这样的赋值语句,会认为定义了一个变量a,然后执行
print(a)的时候,这时候
a = 'in bar‘没有执行,故变量a没有任何绑定值,从而报错。
>>> def bar(): ... print(a) ... a = 'in bar' ... >>> bar() Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 2, in bar UnboundLocalError: local variable 'a' referenced before assignment >>>
2. global
上面函数bar中在执行第一条语句的时候,为什么不去访问全局变量a呢?
这是Python语法规定的,当在函数体中有赋值语句时,编译的时候就认为定义了局部变量,从而保证函数封装性。
如果非得要限定为全局变量,可以使用global关键字。但这种代码要小心,因为很容易就改变了全局变量。
如下代码,最后全局变量a变成了'in bar'。
>>> def bar(): ... global a ... print(a) ... a = 'in bar' ... print(a) ... >>> bar() hello, Python in bar >>> print(a) in bar >>>
3. 闭包与nonlocal
在这里,不得不提下闭包这个概念。在看过很多概念性定义之后,最后在《你不知道的JavaScript》这本书中,终于有了实质性的收获:
当函数可以记住并访问所在的词法作用域时, 就产生了闭包, 即使函数是在当前词法作用域之外执行。
你没有看错,我引用了一本JavaScript书中的定义。抽象性的东西,很多都能通用。
如下代码,在内层函数add中,访问了外层函数中变量count。
每次调用fn都返回一个函数对象,该对象可以在当前全局模块环境中执行,也就是在fn函数词法作用域之外执行。
>>> def fn(): ... count = 0 ... def add(dt = 0): ... r = count + dt ... print(r) ... return add ... >>> fn() <function fn.<locals>.add at 0x7efcd433e048> >>> add = fn() >>> add() 0 >>> add(1) 1 >>> add(123) 123 >>> >>> some = fn() >>> some() 0 >>> some(123) 123 >>>
但是,当我们想要在内层函数直接赋值给外层函数中的变量时,问题就来了。下面的代码,遇到了上面一样的错误。语句
count += dt给count赋值了,Python认为定义了一个局部变量count,+=运算要先取到count的值,但此时内层函数中count没有绑定值,于是报错了。
>>> def fn(): ... count = 0 ... def add(dt = 0): ... count += dt ... print(count) ... return add ... >>> some = fn() >>> some() Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 4, in add UnboundLocalError: local variable 'count' referenced before assignment >>>
可以使用nonlocal来解决这个问题。
注意如下每次函数对象调用的结果,每次调用fn返回的函数对象,该对象持有一份count变量副本,每次调用都针对当前函数对象。
>>> def fn(): ... count = 0 ... def add(dt = 0): ... nonlocal count ... count += dt ... print(count) ... return add ... >>> some = fn() >>> some() 0 >>> some(1) 1 >>> some(123) 124 >>> some(1) 125 >>> >>> any = fn() >>> any() 0 >>> any(1) 1 >>> any(1) 2 >>>
转载于:https://my.oschina.net/athantang/blog/1795481
- 点赞
- 收藏
- 分享
- 文章举报
- python变量总结: 全局变量、局部变量、类变量、实例变量以及global和nonlocal关键字的使用示例
- Python:关键字global和nonlocal的用法说明
- Python nonlocal 与 global 关键字解析
- Python nonlocal 与 global 关键字解析
- Python3 关键字global和nonlocal
- 飘逸的python - 为什么修改全局的dict变量不用global关键字
- python基础 - global关键字及全局变量的用法
- python基础 - global关键字及全局变量的用法
- python基础六:函数的几种类型与局部变量和全局变量、申明修改全局变量global与修改嵌套函数变量的nonlocal
- python:global与nonlocal关键字
- Python3基础 global关键字 使函数的局部变量升格为全局变量
- Python nonlocal 与 global 关键字解析
- python 全局变量的理解(global关键字)
- python3的变量作用域规则和nonlocal关键字
- Python的global和nonlocal关键字(学习)
- 【python】为什么修改全局的dict变量不用global关键字
- Python 关键字global全局变量详解
- Python关键字global与nonlocal区别
- Python中关键字global和nonlocal的区别详解
- Python3基础 nonlocal关键字 内部函数访问到外部函数的变量