在 Python 程序中创建、改变或查找变量名时,都是在一个保存变量名的地方进行中,那个地方我们称之为命名空间。作用域这个术语也称之为命名空间。
具体地说,在代码中变量名被赋值(Python 中变量声明即赋值,global 声明的只是变量的使用域)的位置决定了该变量能被访问的范围。函数定义了本地作用域,而模块定义的是全局作用域。这两个作用域之前有如下关系:
每一个模块都是全局作用域。也就是说,创建于模块文件顶层的变量具有全局作用域,对于外部访问就成了一个模块 对象的属性。
全局作用域的作用范围仅限于单个文件。“全局”指的是在一个文件的顶层变量名对于这个文件而言是全局的。每次对函数的调用都创建了一个新的本地作用域。Python 中也有递归,即可以调用自身,每次调用都会创建五个新的本地命名空间。赋值的变量名除非声明为全局变量,否则均为本地变量。如果需要在函数内部对模块文件顶层的变量名赋值,需要在 函数内部通过 global 语句声明该变量。所有的变量可归纳为本地、全局或者内置三种。范围分别为 def 内部,在一个模块的命名空间内部和预定义的 __builtin__ 模块提供的变量。变量名解析:LEGB 原则
如果对以上内容有所迷惑的话,请看以下总结出的几条原则。在函数命名空间中:
变量名引用分为三个作用域进行查找:首先是本地,然后是函数内(如果有的话),之后是全局,最后是内置。在默认情况下,变量名赋值会创建或者改变本地变量。全局声明将会给映射到模块文件内部的作用域的变量名赋值。Python 的变量名解析机制也称为 LEGB 法则,具体如下:
当在函数中使用未确定的变量名时,Python 搜索 4 个作用域:本地作用域(L),之后是上一层嵌套结构中 def 或 lambda 的本地作用域(E),之后是全局作用域(G),最后是内置作用域(B)。按这个查找原则,在第一处找到的地方停止。如果没有找到,Python 会报错的。 下图说明了搜索流程(由内及外):
作用域实例
# -*- coding: utf8 -*-# 全局作用域 x = 99 # x 和 func 函数在模块中声明,为全局使用域 def func(y): func(1) # func 在模块中定义,可以调用.结果=100 |
以上信息来至:http://magicalboy.com/python-scope-legb.html
另注意比对PHP代码,python代码:
<?php
$s = 3;
function s(){
global $s;
$s = 2;
}
s();
echo $s;//注意输出为 2
test.py
x = 88
y = 2
def func():
global y
#虽然在y在函数内部重新定义前是全局的,
#但是如果函数内有相同的变量那这两个y将是完全不同的变量 了
#所以只能通过global关键字来改变y的值
x = 99
y = 55
func()
print(‘X is %d , Y is %d’%(x,y)) #输出:X is 88 , Y is 55
这里在函数调用前x,y都是全局变量。但当在函数内部遇到同名变量时,已被划分为本地变量。
特别:在函数内部定义的任意的赋值操作变量名都为本地变量:=语句,import,def(注意def 也是赋值操作,上例中将一个函数对象赋值给了func变量),参数传递。
但需要注意本地改变对象时并不会把变量划分为本地变量。如: L.append(x) 并不会让L为本地变量,而L= x 却可以。
转载请注明:爱开源 » python变量的作用域问题