Python中的变量作用域
Python中的作用域
在一般编程语言中,作用域从小到大有块级、函数、类、模块、包五个级别。但是在Python中没有块级作用域的存在,比如for语句中的代码的作用域就和for自身所在的作用域同级(if、with等语句中的代码相同)。
下例在全局作用域中的print函数就可以读取到if语句中的变量a:
if True: a = 0 print(a) # 0
Python作用域的分级结构
Python作用域可分为四个级别:
- 局部作用域 local
- 外部函数的局部作用域 enclosing
- 全局作用域 global
- 内建作用域 built-in
变量/函数的查找顺序:l->e->g->b,当本层没有找到对应的变量/函数后就会去自身的上一层去查找,如果直到内建作用域中也没有找到就会出现变量/函数没有被定义的错误。
a = 0 # global def outer(): a = 1 # enclosing def inner(): a = 2 # local print(a) return inner() outer() # 2
a = 0 # global def outer(): a = 1 # enclosing def inner(): print(a) return inner() outer() # 1
a = 0 # global def outer(): def inner(): print(a) return inner() outer() # 0
在本层中可以访问上一层或更上层的变量,而不能访问下层或更下层的变量。
那么我们能不能在本层中去修改上一层变量的值呢?
a = 0 def func(): b = a print(b) func() # 0
a = 0 def func(): a = a+1 print(a) func() # local variable ‘a‘ referenced before assignment
从上面两例中我们可以发现在本层中虽然可以访问上层的变量,但是不能去修改上层变量的值,上层变量对于下层而言是只读的。
如果需要打破这种限制就要用到global和nonlocal两个关键字。
global和nonlocal
- global:声明变量为全局变量
- nonlocal:可以在闭包函数中引用并使用闭包外层函数的变量
我们将函数func中的a通过global声明为全局变量,这样我们就可以在func中修改全局变量a的值了:
a = 0 def func(): global a a = a+1 print(a) func() # 1
同样的我们可以利用nonlocal在闭包函数的内部函数中去修改外部函数中变量的值:
def outer(): a = 0 def inner(): nonlocal a a = a+1 print(a) return inner() outer() # 1
在Python中还有可以一次性获取所有全局、局部变量的方法:
- globals( ) :以字典的方式存储所有全局变量
- locals ( ):以字典的方式存储所有局部变量
函数作用域
上述案例中我们使用的都是变量,而Python中函数的作用域与变量作用域类似,但有一点我们需要注意:
函数的作用域是自身定义时的位置,而不是调用时的位置。
示例如下:
a = 0 def outer(): a = 1 def inner(): print(a) return inner f = outer() f() # 1
示例中我们先将inner函数返回给了f,并通过f来调用了inner函数,如果结果为0则说明函数作用域是f调用inner时的位置,如果结果为1则说明函数作用域是inner自身定义时的位置。
正确结果正是1。
原文:https://www.cnblogs.com/yeer-xuan/p/13504265.html