函数进阶
作用域
程序的变量并不是在哪个位置都可以访问的,访问权限决定于这个变量是在哪里赋值的,变量的作用域决定了在哪一部分程序可以访问哪个特定的变量名称,python的作用域一共有四种,分别是L(local)--局部作用域,E(enclosing)--闭包函数外的函数中,G(global)--全局作用域,B(buldt-in)内键作用域,以L->E->G->B的规则查找,即:在局部找不到,便会去局部外的局部去找(例如闭包),再找不到就会去全局找,再者去内建找
Python中只有模块(module),类(class)以及函数(def,lambda)才会引入新的作用域,其他的代码块如if/elif/else/try/except.for/while等不会引入新的作用域,也就是说这些语句内定义的变量外部也可以访问
作用域的范围
全局范围(内置名称空间域全局名称空间属于该范围,):全局存活,全局有效
局部范围(局部名称空间属于该范围):临时存活,局部有效
作用域的关系在函数定义截断就已经固定的,与函数的调用位置无关
例子会报出错误,因为在执行程序时的预编译能够在test_scopt()中找到局部变量variable(对variable进行了赋值)在局部作用域找到了变量名,所以不会升级到签到作用域去寻找,但在使用print语句将变量variable打印时局部变量variable并没有绑定搭配一个内存对象(没有定义和初始化,既没有赋值)本质上还是Python调用变量时遵循的LEGB法则和python解释器的编译原理,决定了这个错误的发生,所以在调用一个变量之前,需要为改变量赋值(绑定一个内存对象).在例子中出发的错误是unboundlocalError而不是nameError:name variable is not defined,因为变量variable不在全局作用域,python中的模块代码在执行前并不会经过预编译,但是模块内的函数体代码在运行前会经过预编译,因此不管变量名的绑定发生在作用域的哪个位置都能被编译器知道..
不同作用域的变量的修改
一个非局部变量相对于局部而言,默认是只能读而不能修改的.如果希望在L中修改定义的non_L的变量为其绑定一个新的值,python会认为是在当前的L中引入了一个新的变量(即便内外两个变量重名,但是有着不同的意义)即在当前L中直接使用nonL中的变量,那么这个变量是只读的不能被修改
当希望在L中修改nonL中的变量时可以使用global,nonlocal关键字
如果希望在L中修改G的变量,使用global关键字