-
Notifications
You must be signed in to change notification settings - Fork 3
python notes
在Python程序中创建、改变、查找变量名时,都是在一个保存变量名的空间中进行,我们称之为命名空间,也被称之为作用域。Python的作用域是静态的,在源代码中变量名被赋值的位置决定了该变量能被访问的范围。即Python变量的作用域由变量所在_源代码中的位置_决定。
一般的高级语言在使用变量时,都会有下面4个过程。当然在不同的语言中也会有着区别。
- 声明变量:让编辑器知道有这一个变量的存在
- 定义变量:为不同数据类型的变量分配内存空间
- 初始化:赋值,填充分配好的内存空间
- 引用:通过引用对象(变量名)来调用内存对象(内存数据)
Python没有_块作用域_(if-elif-else、for-else、while、try-except\try-finally等关键字的语句块),只有当变量在Module(模块)、Class(类)、def(函数)中定义的时候,才会有作用域的概念
在Python中,使用一个变量时并不严格要求需要预先声明它,但是在真正使用它之前,它必须被绑定到某个内存对象(被定义、赋值);这种变量名的绑定将在当前作用域中引入新的变量,同时屏蔽外层作用域中的同名变量。
LEGB法则:局部作用域 > 嵌套作用域 > 全局作用域 > 内置作用域
globalVar = 100 #G(global)全局作用域
def test_scope():
enclosingVar = 200 #E(enclosing)嵌套作用域
def func():
localVar = 300 #L(local)局部作用域
print __name__ #B(built-in)内置作用域variable = 300
def test_scopt():
print(variable) #variable是test_scopt()的局部变量,但是在打印时并没有绑定内存对象。
variable = 200
test_scopt()
print(variable)代码输出为:
UnboundLocalError: local variable 'variable' referenced before assignment
上面的例子会报出错误,因为在执行程序时的__预编译__能够在test_scopt()中找到局部变量variable(对variable进行了赋值)。在局部作用域找到了变量名,所以__不会__升级到嵌套作用域去寻找。但是在使用print语句将变量variable打印时,局部变量variable并没有没绑定到一个内存对象(没有定义和初始化,即没有赋值)。本质上还是Python调用变量时遵循的LEGB法则和Python解析器的编译原理,决定了这个错误的发生。所以,在调用一个变量之前,需要为该变量赋值(绑定一个内存对象)。
注意:为什么在这个例子中触发的错误是UnboundLocalError而不是NameError:name ‘variable’ is not defined。因为变量variable不在全局作用域。Python中的_模块代码_在执行之前,并不会经过预编译,但是模块内的_函数体代码_在运行前会经过预编译,因此不管变量名的绑定发生在作用域的那个位置,都能被编译器知道。Python虽然是一个静态作用域语言,但变量名查找是动态发生的,直到在程序运行时,才会发现作用域方面的问题。
JavaScript 中,函数及变量的声明都将被提升到函数的最顶部。
JavaScript 中,变量可以在使用后声明,也就是变量可以先使用再声明。
console.log(a);//undefined
var a = 10;
console.log(a);//10等价于
var a ; //声明变量
console.log(a);
a = 10; //初始化
console.log(a);-
在
L中修改G中的变量,使用global关键字spam = 99 def tester(): def nested(): global spam print('current=',spam) spam = 200 return nested tester()() print spam
输出为:
('current=', 99) 200 -
在
L中修改E中的变量,使用nonlocal关键字def outer(): count = 10 def inner(): nonlocal count count = 20 print(count) inner() print(count) outer()
输出为:
20 20
Python支持一种特性叫做函数闭包(function closures):在非全局(global)作用域中定义inner函数(即嵌套函数)时,会记录下它的嵌套函数namespaces(嵌套函数作用域的locals),可以称作:定义时状态,可以通过func_closure这个属性来获得inner函数的外层嵌套函数的namespaces。
例子:
def outer(x):
def inner():
print x # 1
return inner
print1 = outer(1)
print2 = outer(2)
print print1.func_closure
print1()
print print2.func_closure
print2()输出为:
(<cell at 0x147d3328: int object at 0x146b2d08>,) #这里面里面保存了一个int对象,这个int对象就是x
1
(<cell at 0x147d3360: int object at 0x146b2cf0>,)
2