Python 是一种静态范围的语言,尽管它本身是一种动态语言。换句话说,Python中变量的作用域是由它在源代码中的位置决定的,这与C有些相似,但是Python和C在作用域上的区别还是很明显的。
Python的作用域规则,中间也会说明Python和C在作用域方面的区别。
在 Python 2.0 及更早的版本中,Python 仅支持三种作用域,即局部作用域、全局作用域和内置作用域;在 Python 2.2 中,Python 正式引入了一个新的作用域——嵌套作用域;在 Python 2.1 中,可以选择启用嵌套作用域;嵌套作用域的引入本质上实现了对 Python 闭包的支持。网上关于闭包的解释很多,这里就不详细展开了。因此,变量搜索顺序从 LGB 更改为 LEGB(L:本地,E:封闭,G:全局,B:内置)。
在 Python 中,不是任何代码块都可以引入新的作用域,这一点与 C 有很大不同:
代码如下:
#include
int main() {
if(2 > 0) {
int i = 0;
}
printf("i = %d", i);
return 0;
}
在这段代码中,if子句引入了一个局部作用域,变量i存在于这个局部作用域中,但对外是不可见的。因此,下面在printf函数中引用变量i会导致编译错误。
但是,在Python中却并非如此:
代码如下:
if True:
i = 0
print i
在这段代码中,if 子句没有引入局部作用域,变量 i 仍然在全局作用域内,因此变量 i 对后面的 print 语句是可见的。
事实上,在 Python 中,只有模块、类和函数引入了新的作用域,其他代码块不会引入新的作用域。
在 Python 中,不需要在使用之前预先声明一个变量,但在实际使用之前必须绑定一个对象;而名称绑定会在当前作用域内引入新的变量,同时屏蔽外层作用域内同名的变量,无论名称绑定发生在当前作用域的哪个位置。
代码如下:
def f():
print i
f()
运行结果会显示:NameError: global name 'i' is not defined。 Python首先在函数f的局部作用域查找变量i,查找失败,然后在全局作用域和内置作用域查找变量i,仍然失败,最后抛出NameError异常。
代码如下:
i = 0
def f():
i = 8
print i
f()
print i
运行结果显示:8和0。i=8是名字绑定操作,在函数f的局部作用域内引入了一个新变量i,屏蔽了全局变量i,所以f里面的print语句看到的是局部变量i ,而在 f 之外的 print 语句,该语句看到的是全局变量 i。
代码如下:
i = 0
def f():
print i
i = 0
f()
运行结果显示:UnboundLocalError: local variable 'i' referenced before assignment。在这个例子中,函数f中的变量i是一个局部变量,但是当print语句使用它的时候,它还没有绑定到任何对象,所以会抛出异常。
代码如下:
print i
i = 0
无论是交互运行还是作为脚本文件运行,结果显示:NameError: name 'i' is not defined。这里的输出又和前面的例子不一样了,因为它是在顶级作用域(模块作用域)。对于模块代码,代码在执行前没有进行预处理,而对于函数体,代码在运行前已经进行了预处理,所以无论名称绑定发生在作用域的什么地方,都能感觉到。尽管 Python 是一种静态范围的语言,但名称查找确实是动态发生的,因此直到运行时才发现名称问题。
在 Python 中,名称绑定在绑定到对象时会在拥有范围内引入新变量。名称绑定发生在以下情况:
1.参数声明:参数声明在函数的局部范围内引入了一个新变量;
2、赋值操作:对一个变量的初始赋值会在当前作用域中引入一个新变量,后续的赋值操作会重新绑定该变量;
3、类和函数定义:类和函数定义将类名和函数名作为变量引入当前作用域,类体和函数体会形成另一个作用域;
4、import语句:import语句在当前范围内引入新变量,一般在全局范围内;
5.for语句:for语句在当前作用域引入了一个新变量(循环变量);
6. except 语句: except 语句在当前范围内引入新的变量(异常对象)。
在 Python 中,类定义引入的作用域对成员函数是不可见的,这与 C++ 或 Java 有很大不同。因此,在 Python 中,如果一个成员函数想要引用一个由类体定义的变量,它必须通过 self 或类名来引用它。
添加嵌套作用域会导致部分代码编译失败或运行结果不同。在这里,Python 解释器将帮助你识别这些可能的问题并给出警告。
locals 函数返回所有局部变量,但不返回嵌套作用域中的变量。事实上,没有函数返回嵌套作用域中的变量。
本文为原创文章,版权归知行编程网所有,欢迎分享本文,转载请保留出处!
你可能也喜欢
- ♥ 如何在 python 中使用 namedtuple?01/11
- ♥ 如何用python写内容12/27
- ♥ 什么是python链表12/12
- ♥ 在python中排序时不区分大小写11/24
- ♥ 如何取消python中的换行符10/05
- ♥ 如何在python中复制文件夹11/08
内容反馈